Remove obsoleted vts/utils/python/

Bug: none
Test: build
Change-Id: I7bf60e3476c805454c8fbd54b52b3452043716e6
diff --git a/utils/python/coverage/Android.mk b/utils/python/coverage/Android.mk
deleted file mode 100644
index a4eb9db..0000000
--- a/utils/python/coverage/Android.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright 2016 - 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := vts_coverage_test
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_MODULE_CLASS := FAKE
-LOCAL_IS_HOST_MODULE := true
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-py_scripts := \
-  $(LOCAL_PATH)/parser_test.py \
-  $(LOCAL_PATH)/gcno_parser_test.py \
-  $(LOCAL_PATH)/gcda_parser_test.py \
-  $(LOCAL_PATH)/arc_summary_test.py \
-  $(LOCAL_PATH)/function_summary_test.py \
-  $(LOCAL_PATH)/coverage_report_test.py \
-
-test_dependencies := \
-  $(LOCAL_PATH)/testdata/sample.gcno \
-  $(LOCAL_PATH)/testdata/sample.gcda
-
-$(LOCAL_BUILT_MODULE): PRIVATE_PY_SCRIPTS := $(py_scripts)
-$(LOCAL_BUILT_MODULE): $(py_scripts) $(test_dependencies)
-	@echo "Regression test (build time): $(PRIVATE_MODULE)"
-	$(foreach py, $(PRIVATE_PY_SCRIPTS), (PYTHONPATH=$$PYTHONPATH:test python $(py)) &&) true
-	$(hide) touch $@
diff --git a/utils/python/coverage/README.md b/utils/python/coverage/README.md
deleted file mode 100644
index 3c11a9b..0000000
--- a/utils/python/coverage/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# To run from another Python module
-
-Import the CoverageReport module by including the line:
-
-   from vts.utils.python.coverage import CoverageReport
-
-Run the code by calling the parse function as follows:
-   html_report = CoverageReport.GenerateCoverageReport(src_file_name, src_file_content, gcov_file_content,
-                           gcda_file_content)
-
-Args:
-    src_file_name: string, the source file name.
-    src_file_content: string, the C/C++ source file content.
-    gcov_file_content: string, the raw gcov binary file content.
-    gcda_file_content: string, the raw gcda binary file content.
-
-Returns:
-    the coverage HTML produced for 'src_file_name'.
diff --git a/utils/python/coverage/__init__.py b/utils/python/coverage/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/utils/python/coverage/__init__.py
+++ /dev/null
diff --git a/utils/python/coverage/arc_summary.py b/utils/python/coverage/arc_summary.py
deleted file mode 100644
index ae9138f..0000000
--- a/utils/python/coverage/arc_summary.py
+++ /dev/null
@@ -1,90 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-
-class ArcSummary(object):
-    """Summarizes an arc from a .gcno file.
-
-    Attributes:
-        src_block_index: integer index of the source basic block.
-        dstBlockIndex: integer index of the destination basic block.
-        on_tree: True iff arc has flag GCOV_ARC_ON_TREE.
-        fake: True iff arc has flag GCOV_ARC_FAKE.
-        fallthrough: True iff arc has flag GCOV_ARC_FALLTHROUGH.
-        resolved: True iff the arc's count has been resolved.
-        count: Integer number of times the arc was covered.
-    """
-
-    GCOV_ARC_ON_TREE = 1
-    GCOV_ARC_FAKE = 1 << 1
-    GCOV_ARC_FALLTHROUGH = 1 << 2
-
-    def __init__(self, src_block, dst_block, flag):
-        """Inits the arc summary with provided values.
-
-        Stores the source and destination block indices and parses
-        the arc flag.
-
-        Args:
-            src_block: BlockSummary of source block.
-            dst_block: BlockSummary of destination block.
-            flag: integer flag for the given arc.
-        """
-
-        self.src_block = src_block
-        self.dst_block = dst_block
-        self.on_tree = bool(flag & self.GCOV_ARC_ON_TREE)
-        self.fake = bool(flag & self.GCOV_ARC_FAKE)
-        self.fallthrough = bool(flag & self.GCOV_ARC_FALLTHROUGH)
-        self.resolved = False
-        self.count = 0
-
-    def Resolve(self):
-        """Resolves the arc count and returns True if successful.
-
-        Uses the property that the sum of counts of arcs entering a
-        node is equal to the sum of counts of arcs leaving a node. The
-        exception to this rule is fake non-fallthrough nodes, which have
-        no exit edges. In this case, remove the arc as an exit arc from
-        the source so that the source can be resolved.
-
-        Returns:
-            True if the arc could be resolved and False otherwise.
-        """
-        if self.fake and not self.fallthrough:
-            try:
-                self.src_block.exit_arcs.remove(self)
-            except ValueError:
-                pass
-        elif (len(self.src_block.entry_arcs) > 0 and
-              all(a.resolved for a in self.src_block.entry_arcs) and
-              all(a.resolved for a in self.src_block.exit_arcs if a != self)):
-            in_flow = sum(a.count for a in self.src_block.entry_arcs)
-            out_flow = sum(a.count for a in self.src_block.exit_arcs
-                           if a != self)
-            self.count = in_flow - out_flow
-            self.resolved = True
-        elif (len(self.dst_block.exit_arcs) > 0 and
-              all(a.resolved for a in self.dst_block.exit_arcs) and
-              all(a.resolved for a in self.dst_block.entry_arcs if a != self)):
-            out_flow = sum(a.count for a in self.dst_block.exit_arcs)
-            in_flow = sum(a.count for a in self.dst_block.entry_arcs
-                          if a != self)
-            self.count = out_flow - in_flow
-            self.resolved = True
-        else:
-            return False
-        return True
diff --git a/utils/python/coverage/arc_summary_test.py b/utils/python/coverage/arc_summary_test.py
deleted file mode 100644
index 6784be7..0000000
--- a/utils/python/coverage/arc_summary_test.py
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2016 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.
-#
-
-import os
-import unittest
-
-from vts.utils.python.coverage import arc_summary
-from vts.utils.python.coverage import block_summary
-
-
-class ArcSummaryTest(unittest.TestCase):
-    """Tests for ArcSummary of vts.utils.python.coverage.
-    """
-
-    def testResolveRemove(self):
-        """Verifies that fake, non-fallthrough arc are resolved correctly.
-
-        The arc should be removed as an exit arc from the source.
-        """
-        src = block_summary.BlockSummary(0, 0)
-        dst = block_summary.BlockSummary(1, 0)
-        flag = arc_summary.ArcSummary.GCOV_ARC_FAKE
-        arc = arc_summary.ArcSummary(src, dst, flag)
-        src.exit_arcs.append(arc)
-        dst.entry_arcs.append(arc)
-        self.assertTrue(arc.Resolve())
-        self.assertEqual(len(src.exit_arcs), 0)
-
-    def testResolveFromSource(self):
-        """Verifies that arcs can be resolved from the source.
-
-        In the case when the source has fully-resolved entry arcs, the arc
-        count should be resolved from the source. I.e. there is only one
-        missing arc and it can be solved for from the source.
-        """
-        middle = block_summary.BlockSummary(-1, 0)
-        n = 10
-
-        # Create resolved arcs entering the middle block
-        for ident in range(n):
-            block = block_summary.BlockSummary(ident, 0)
-            arc = arc_summary.ArcSummary(block, middle, 0)
-            arc.resolved = True
-            arc.count = 1
-            block.exit_arcs.append(arc)
-            middle.entry_arcs.append(arc)
-
-        # Create resolved arcs exiting the middle block
-        for ident in range(n, 2 * n - 1):
-            block = block_summary.BlockSummary(ident, 0)
-            arc = arc_summary.ArcSummary(middle, block, 0)
-            arc.resolved = True
-            arc.count = 1
-            block.entry_arcs.append(arc)
-            middle.exit_arcs.append(arc)
-
-        # Create one unresolved arc exiting the middle
-        last = block_summary.BlockSummary(2 * n - 1, 0)
-        arc = arc_summary.ArcSummary(middle, last, 0)
-        middle.exit_arcs.append(arc)
-        last.entry_arcs.append(arc)
-        self.assertTrue(arc.Resolve())
-        self.assertTrue(arc.resolved)
-        self.assertEqual(arc.count, 1)
-
-    def testResolveFromDest(self):
-        """Verifies that arcs can be resolved from the destination block.
-
-        In the case when the source has fully-resolved exit arcs, the arc
-        count should be resolved from the source. I.e. there is only one
-        missing arc and it can be solved for from the destination.
-        """
-        middle = block_summary.BlockSummary(-1, 0)
-        n = 10
-
-        # Create resolved arcs exiting the middle block
-        for ident in range(n):
-            block = block_summary.BlockSummary(ident, 0)
-            arc = arc_summary.ArcSummary(middle, block, 0)
-            arc.resolved = True
-            arc.count = 1
-            block.entry_arcs.append(arc)
-            middle.exit_arcs.append(arc)
-
-        # Create resolved arcs entering the middle block
-        for ident in range(n, 2 * n - 1):
-            block = block_summary.BlockSummary(ident, 0)
-            arc = arc_summary.ArcSummary(block, middle, 0)
-            arc.resolved = True
-            arc.count = 1
-            block.exit_arcs.append(arc)
-            middle.entry_arcs.append(arc)
-
-        # Create one unresolved arc entering the middle
-        block = block_summary.BlockSummary(2 * n - 1, 0)
-        arc = arc_summary.ArcSummary(block, middle, 0)
-        middle.entry_arcs.append(arc)
-        block.exit_arcs.append(arc)
-        self.assertTrue(arc.Resolve())
-        self.assertTrue(arc.resolved)
-        self.assertEqual(arc.count, 1)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/utils/python/coverage/block_summary.py b/utils/python/coverage/block_summary.py
deleted file mode 100644
index 794ea9b..0000000
--- a/utils/python/coverage/block_summary.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-
-class BlockSummary(object):
-    """Summarizes a block of code from a .gcno file.
-
-    Contains all the lines in the block and the entry/exit
-    arcs from/to other basic blocks.
-
-    Attributes:
-        flag: integer flag value.
-        entry_arcs: list of ArcSummary objects for each arc
-        entering the code block.
-        exit_arcs: list of ArcSummary objects for each arc exiting
-        the code block.
-        lines: list of line numbers represented by the basic block.
-    """
-
-    def __init__(self, index, flag):
-        """Inits the block summary with provided values.
-
-        Initializes entryArcs, exitArcs, and lines to the empty list.
-        Stores the block flag in the flag attribute.
-
-        Args:
-            index: the basic block number
-            flag: integer block flag.
-        """
-        self.index = index
-        self.flag = flag
-        self.entry_arcs = []
-        self.exit_arcs = []
-        self.count = 0
-        self.lines = []
-
-    def __str__(self):
-        """Serializes the block summary as a string.
-
-        Returns:
-            String representation of the block.
-        """
-        output = '\tBlock: %i, Count: %i' % (self.index, self.count)
-        if len(self.lines):
-            output += ', Lines: ' + ', '.join(str(line) for line in self.lines)
-        if len(self.entry_arcs):
-            output += ('\r\n\t\t' + str(self.index) + '  <--  ' + ', '.join(
-                str(a.src_block.index) for a in self.entry_arcs))
-        if len(self.exit_arcs):
-            output += ('\r\n\t\t' + str(self.index) + '  -->  ' + ', '.join(
-                str(a.dst_block.index) for a in self.exit_arcs))
-        return output + '\r\n'
diff --git a/utils/python/coverage/coverage_report.py b/utils/python/coverage/coverage_report.py
deleted file mode 100644
index c176e5f..0000000
--- a/utils/python/coverage/coverage_report.py
+++ /dev/null
@@ -1,100 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-"""Generates coverage reports using outputs from GCC.
-
-The GenerateCoverageReport() function returns HTML to display the coverage
-at each line of code in a provided source file. Coverage information is
-parsed from .gcno and .gcda file contents and combined with the source file
-to reconstruct a coverage report. GenerateLineCoverageVector() is a helper
-function that produces a vector of line counts and GenerateCoverageHTML()
-uses the vector and source to produce the HTML coverage report.
-"""
-
-import cgi
-import io
-import logging
-import os
-from vts.utils.python.coverage import gcda_parser
-from vts.utils.python.coverage import gcno_parser
-
-GEN_TAG = "/gen/"
-
-def GenerateLineCoverageVector(gcno_file_summary, exclude_paths, coverage_dict):
-    """Process the gcno_file_summary and update the coverage dictionary.
-
-    Create a coverage vector for each source file contained in gcno_file_summary
-    and update the corresponding item in coverage_dict.
-
-    Args:
-        gcno_file_summary: FileSummary object after gcno and gcda files have
-                           been parsed.
-        exclude_paths: a list of paths should be ignored in the coverage report.
-        coverage_dict: a dictionary for each source file and its corresponding
-                       coverage vector.
-    """
-    for ident in gcno_file_summary.functions:
-        func = gcno_file_summary.functions[ident]
-        file_name = func.src_file_name
-        if GEN_TAG in file_name:
-            logging.debug("Skip generated source file %s.", file_name)
-            continue
-        skip_file = False
-        for path in exclude_paths:
-            if file_name.startswith(path):
-                skip_file = True
-                break
-        if skip_file:
-            logging.debug("Skip excluded source file %s.", file_name)
-            continue
-
-        src_lines_counts = coverage_dict[file_name] if file_name in coverage_dict else []
-        for block in func.blocks:
-            for line in block.lines:
-                if line > len(src_lines_counts):
-                    src_lines_counts.extend([-1] *
-                                            (line - len(src_lines_counts)))
-                if src_lines_counts[line - 1] < 0:
-                    src_lines_counts[line - 1] = 0
-                src_lines_counts[line - 1] += block.count
-        coverage_dict[file_name] = src_lines_counts
-
-
-def GetCoverageStats(src_lines_counts):
-    """Returns the coverage stats.
-
-    Args:
-        src_lines_counts: A list of non-negative integers or -1 representing
-                          the number of times the i-th line was executed.
-                          -1 indicates a line that is not executable.
-
-    Returns:
-        integer, the number of lines instrumented for coverage measurement
-        integer, the number of executed or covered lines
-    """
-    total = 0
-    covered = 0
-    if not src_lines_counts or not isinstance(src_lines_counts, list):
-        logging.error("GetCoverageStats: input invalid.")
-        return total, covered
-
-    for line in src_lines_counts:
-        if line < 0:
-            continue
-        total += 1
-        if line > 0:
-            covered += 1
-    return total, covered
-
diff --git a/utils/python/coverage/coverage_report_test.py b/utils/python/coverage/coverage_report_test.py
deleted file mode 100644
index 049d84c..0000000
--- a/utils/python/coverage/coverage_report_test.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2016 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.
-#
-
-import os
-import unittest
-
-from vts.utils.python.coverage import gcno_parser
-from vts.utils.python.coverage import gcda_parser
-from vts.utils.python.coverage import coverage_report
-
-
-class CoverageReportTest(unittest.TestCase):
-    """Unit tests for CoverageReport of vts.utils.python.coverage.
-    """
-
-    GOLDEN_GCNO_PATH = 'testdata/sample.gcno'
-    GOLDEN_GCDA_PATH = 'testdata/sample.gcda'
-
-    @classmethod
-    def setUpClass(cls):
-        dir_path = os.path.dirname(os.path.realpath(__file__))
-        gcno_path = os.path.join(dir_path, cls.GOLDEN_GCNO_PATH)
-        with open(gcno_path, 'rb') as file:
-            gcno_summary = gcno_parser.GCNOParser(file).Parse()
-        gcda_path = os.path.join(dir_path, cls.GOLDEN_GCDA_PATH)
-        with open(gcda_path, 'rb') as file:
-            parser = gcda_parser.GCDAParser(file)
-            parser.Parse(gcno_summary)
-        cls.gcno_summary = gcno_summary
-
-    def testGenerateLineCoverageVector(self):
-        """Tests that coverage vector is correctly generated.
-
-        Runs GenerateLineCoverageVector on sample file and checks
-        result.
-        """
-        coverage_dict = dict()
-        exclude_paths = []
-        src_lines_counts = coverage_report.GenerateLineCoverageVector(
-            self.gcno_summary, exclude_paths, coverage_dict)
-        expected = {'sample.c': [-1, -1, -1, -1, 2, -1, -1, -1, -1, -1, 2,
-                    2, 2, -1, 2, -1, 2, 0, -1, 2, -1, -1, 2, 2, 502,
-                    500, -1, -1, 2, -1, 2, -1, -1, -1, 2, -1,
-                    -1, -1, -1, 2, 2, 2]}
-        self.assertEqual(coverage_dict, expected)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/utils/python/coverage/coverage_utils.py b/utils/python/coverage/coverage_utils.py
deleted file mode 100644
index 217b028..0000000
--- a/utils/python/coverage/coverage_utils.py
+++ /dev/null
@@ -1,771 +0,0 @@
-#
-# Copyright (C) 2016 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.
-import argparse
-import io
-import json
-import logging
-import os
-import shutil
-import sys
-import time
-import zipfile
-
-from vts.proto import VtsReportMessage_pb2 as ReportMsg
-from vts.runners.host import keys
-from vts.utils.python.archive import archive_parser
-from vts.utils.python.common import cmd_utils
-from vts.utils.python.controllers.adb import AdbError
-from vts.utils.python.coverage import coverage_report
-from vts.utils.python.coverage import gcda_parser
-from vts.utils.python.coverage import gcno_parser
-from vts.utils.python.coverage.parser import FileFormatError
-from vts.utils.python.os import path_utils
-from vts.utils.python.web import feature_utils
-
-FLUSH_PATH_VAR = "GCOV_PREFIX"  # environment variable for gcov flush path
-TARGET_COVERAGE_PATH = "/data/misc/trace/"  # location to flush coverage
-LOCAL_COVERAGE_PATH = "/tmp/vts-test-coverage"  # location to pull coverage to host
-
-# Environment for test process
-COVERAGE_TEST_ENV = "GCOV_PREFIX_OVERRIDE=true GCOV_PREFIX=/data/misc/trace/self"
-
-GCNO_SUFFIX = ".gcno"
-GCDA_SUFFIX = ".gcda"
-COVERAGE_SUFFIX = ".gcnodir"
-GIT_PROJECT = "git_project"
-MODULE_NAME = "module_name"
-NAME = "name"
-PATH = "path"
-GEN_TAG = "/gen/"
-
-_BUILD_INFO = "BUILD_INFO"  # name of build info artifact
-_GCOV_ZIP = "gcov.zip"  # name of gcov artifact zip
-_REPO_DICT = "repo-dict"  # name of dictionary from project to revision in BUILD_INFO
-
-_CLEAN_TRACE_COMMAND = "rm -rf /data/misc/trace/*"
-_FLUSH_COMMAND = (
-    "GCOV_PREFIX_OVERRIDE=true GCOV_PREFIX=/data/local/tmp/flusher "
-    "/data/local/tmp/vts_coverage_configure flush")
-_SP_COVERAGE_PATH = "self"  # relative location where same-process coverage is dumped.
-
-_CHECKSUM_GCNO_DICT = "checksum_gcno_dict"
-_COVERAGE_ZIP = "coverage_zip"
-_REVISION_DICT = "revision_dict"
-
-
-class CoverageFeature(feature_utils.Feature):
-    """Feature object for coverage functionality.
-
-    Attributes:
-        enabled: boolean, True if coverage is enabled, False otherwise
-        web: (optional) WebFeature, object storing web feature util for test run
-        local_coverage_path: path to store the coverage files.
-        _device_resource_dict: a map from device serial number to host resources directory.
-        _hal_names: the list of hal names for which to process coverage.
-        _coverage_report_file_prefix: prefix of the output coverage report file.
-    """
-
-    _TOGGLE_PARAM = keys.ConfigKeys.IKEY_ENABLE_COVERAGE
-    _REQUIRED_PARAMS = [keys.ConfigKeys.IKEY_ANDROID_DEVICE]
-    _OPTIONAL_PARAMS = [
-        keys.ConfigKeys.IKEY_MODULES,
-        keys.ConfigKeys.IKEY_OUTPUT_COVERAGE_REPORT,
-        keys.ConfigKeys.IKEY_GLOBAL_COVERAGE,
-        keys.ConfigKeys.IKEY_EXCLUDE_COVERAGE_PATH,
-        keys.ConfigKeys.IKEY_COVERAGE_REPORT_PATH,
-    ]
-
-    _DEFAULT_EXCLUDE_PATHS = [
-        "bionic", "external/libcxx", "system/core", "system/libhidl",
-        "system/libfmq"
-    ]
-
-    def __init__(self, user_params, web=None):
-        """Initializes the coverage feature.
-
-        Args:
-            user_params: A dictionary from parameter name (String) to parameter value.
-            web: (optional) WebFeature, object storing web feature util for test run
-            local_coverage_path: (optional) path to store the .gcda files and coverage reports.
-        """
-        self.ParseParameters(self._TOGGLE_PARAM, self._REQUIRED_PARAMS,
-                             self._OPTIONAL_PARAMS, user_params)
-        self.web = web
-        self._device_resource_dict = {}
-        self._hal_names = None
-
-        timestamp_seconds = str(int(time.time() * 1000000))
-        self.local_coverage_path = os.path.join(LOCAL_COVERAGE_PATH,
-                                                timestamp_seconds)
-        if os.path.exists(self.local_coverage_path):
-            logging.debug("removing existing coverage path: %s",
-                          self.local_coverage_path)
-            shutil.rmtree(self.local_coverage_path)
-        os.makedirs(self.local_coverage_path)
-
-        self._coverage_report_dir = getattr(
-            self, keys.ConfigKeys.IKEY_COVERAGE_REPORT_PATH, None)
-
-        self._coverage_report_file_prefix = ""
-
-        self.global_coverage = getattr(
-            self, keys.ConfigKeys.IKEY_GLOBAL_COVERAGE, True)
-        if self.enabled:
-            android_devices = getattr(self,
-                                      keys.ConfigKeys.IKEY_ANDROID_DEVICE)
-            if not isinstance(android_devices, list):
-                logging.warn("Android device information not available.")
-                self.enabled = False
-            for device in android_devices:
-                serial = device.get(keys.ConfigKeys.IKEY_SERIAL)
-                coverage_resource_path = device.get(
-                    keys.ConfigKeys.IKEY_GCOV_RESOURCES_PATH)
-                if not serial:
-                    logging.error("Missing serial information in device: %s",
-                                  device)
-                    continue
-                if not coverage_resource_path:
-                    logging.error(
-                        "Missing coverage resource path in device: %s", device)
-                    continue
-                self._device_resource_dict[str(serial)] = str(
-                    coverage_resource_path)
-
-        if self.enabled:
-            logging.info("Coverage is enabled")
-        else:
-            logging.debug("Coverage is disabled.")
-
-    def _FindGcnoSummary(self, gcda_file_path, gcno_file_parsers):
-        """Find the corresponding gcno summary for given gcda file.
-
-        Identify the corresponding gcno summary for given gcda file from a list
-        of gcno files with the same checksum as the gcda file by matching
-        the the gcda file path.
-        Note: if none of the gcno summary contains the source file same as the
-        given gcda_file_path (e.g. when the corresponding source file does not
-        contain any executable codes), just return the last gcno summary in the
-        list as a fall back solution.
-
-        Args:
-            gcda_file_path: the path of gcda file (without extensions).
-            gcno_file_parsers: a list of gcno file parser that has the same
-                               chechsum.
-
-        Returns:
-            The corresponding gcno summary for given gcda file.
-        """
-        gcno_summary = None
-        # For each gcno files with the matched checksum, compare the
-        # gcda_file_path to find the corresponding gcno summary.
-        for gcno_file_parser in gcno_file_parsers:
-            try:
-                gcno_summary = gcno_file_parser.Parse()
-            except FileFormatError:
-                logging.error("Error parsing gcno for gcda %s", gcda_file_path)
-                break
-            legacy_build = "soong/.intermediates" not in gcda_file_path
-            for key in gcno_summary.functions:
-                src_file_path = gcno_summary.functions[key].src_file_name
-                src_file_name = src_file_path.rsplit(".", 1)[0]
-                # If build with legacy compile system, compare only the base
-                # source file name. Otherwise, compare the full source file name
-                # (with path info).
-                if legacy_build:
-                    base_src_file_name = os.path.basename(src_file_name)
-                    if gcda_file_path.endswith(base_src_file_name):
-                        return gcno_summary
-                else:
-                    if gcda_file_path.endswith(src_file_name):
-                        return gcno_summary
-        # If no gcno file matched with the gcda_file_name, return the last
-        # gcno summary as a fall back solution.
-        return gcno_summary
-
-    def _GetChecksumGcnoDict(self, cov_zip):
-        """Generates a dictionary from gcno checksum to GCNOParser object.
-
-        Processes the gcnodir files in the zip file to produce a mapping from gcno
-        checksum to the GCNOParser object wrapping the gcno content.
-        Note there might be multiple gcno files corresponds to the same checksum.
-
-        Args:
-            cov_zip: the zip file containing gcnodir files from the device build
-
-        Returns:
-            the dictionary of gcno checksums to GCNOParser objects
-        """
-        checksum_gcno_dict = dict()
-        fnames = cov_zip.namelist()
-        instrumented_modules = [
-            f for f in fnames if f.endswith(COVERAGE_SUFFIX)
-        ]
-        for instrumented_module in instrumented_modules:
-            # Read the gcnodir file
-            archive = archive_parser.Archive(
-                cov_zip.open(instrumented_module).read())
-            try:
-                archive.Parse()
-            except ValueError:
-                logging.error("Archive could not be parsed: %s", name)
-                continue
-
-            for gcno_file_path in archive.files:
-                gcno_stream = io.BytesIO(archive.files[gcno_file_path])
-                gcno_file_parser = gcno_parser.GCNOParser(gcno_stream)
-                if gcno_file_parser.checksum in checksum_gcno_dict:
-                    checksum_gcno_dict[gcno_file_parser.checksum].append(
-                        gcno_file_parser)
-                else:
-                    checksum_gcno_dict[gcno_file_parser.checksum] = [
-                        gcno_file_parser
-                    ]
-        return checksum_gcno_dict
-
-    def _ClearTargetGcov(self, dut, serial, path_suffix=None):
-        """Removes gcov data from the device.
-
-        Finds and removes all gcda files relative to TARGET_COVERAGE_PATH.
-        Args:
-            dut: the device under test.
-            path_suffix: optional string path suffix.
-        """
-        path = TARGET_COVERAGE_PATH
-        if path_suffix:
-            path = path_utils.JoinTargetPath(path, path_suffix)
-        self._ExecuteOneAdbShellCommand(dut, serial, _CLEAN_TRACE_COMMAND)
-
-    def _GetHalPids(self, dut, hal_names):
-        """Get the process id for the given hal names.
-
-        Args:
-            dut: the device under test.
-            hal_names: list of strings for targeting hal names.
-
-        Returns:
-            list of strings for the corresponding pids.
-        """
-        logging.debug("hal_names: %s", str(hal_names))
-        searchString = "|".join(hal_names)
-        entries = []
-        try:
-            dut.rootAdb()
-            entries = dut.adb.shell(
-                "lshal -itp 2> /dev/null | grep -E \"{0}\"".format(
-                    searchString)).splitlines()
-        except AdbError as e:
-            logging.error("failed to get pid entries")
-
-        pids = set(pid.strip()
-                   for pid in map(lambda entry: entry.split()[-1], entries)
-                   if pid.isdigit())
-        return pids
-
-    def InitializeDeviceCoverage(self, dut=None, serial=None):
-        """Initializes the device for coverage before tests run.
-
-        Flushes, then finds and removes all gcda files under
-        TARGET_COVERAGE_PATH before tests run.
-
-        Args:
-            dut: the device under test.
-        """
-        self._ExecuteOneAdbShellCommand(dut, serial, "setenforce 0")
-        self._ExecuteOneAdbShellCommand(dut, serial, _FLUSH_COMMAND)
-        logging.debug("Removing existing gcda files.")
-        self._ClearTargetGcov(dut, serial)
-
-        # restart HALs to include coverage for initialization code.
-        if self._hal_names:
-            pids = self._GetHalPids(dut, self._hal_names)
-            for pid in pids:
-                cmd = "kill -9 " + pid
-                self._ExecuteOneAdbShellCommand(dut, serial, cmd)
-
-    def _GetGcdaDict(self, dut, serial):
-        """Retrieves GCDA files from device and creates a dictionary of files.
-
-        Find all GCDA files on the target device, copy them to the host using
-        adb, then return a dictionary mapping from the gcda basename to the
-        temp location on the host.
-
-        Args:
-            dut: the device under test.
-
-        Returns:
-            A dictionary with gcda basenames as keys and contents as the values.
-        """
-        logging.debug("Creating gcda dictionary")
-        gcda_dict = {}
-        logging.debug("Storing gcda tmp files to: %s",
-                      self.local_coverage_path)
-
-        self._ExecuteOneAdbShellCommand(dut, serial, _FLUSH_COMMAND)
-
-        gcda_files = set()
-        if self._hal_names:
-            pids = self._GetHalPids(dut, self._hal_names)
-            pids.add(_SP_COVERAGE_PATH)
-            for pid in pids:
-                path = path_utils.JoinTargetPath(TARGET_COVERAGE_PATH, pid)
-                try:
-                    files = dut.adb.shell("find %s -name \"*.gcda\"" % path)
-                    gcda_files.update(files.split("\n"))
-                except AdbError as e:
-                    logging.info("No gcda files found in path: \"%s\"", path)
-        else:
-            cmd = ("find %s -name \"*.gcda\"" % TARGET_COVERAGE_PATH)
-            result = self._ExecuteOneAdbShellCommand(dut, serial, cmd)
-            if result:
-                gcda_files.update(result.split("\n"))
-
-        for gcda in gcda_files:
-            if gcda:
-                basename = os.path.basename(gcda.strip())
-                file_name = os.path.join(self.local_coverage_path, basename)
-                if dut is None:
-                    results = cmd_utils.ExecuteShellCommand(
-                        "adb -s %s pull %s %s " % (serial, gcda, file_name))
-                    if (results[cmd_utils.EXIT_CODE][0]):
-                        logging.error(
-                            "Fail to execute command: %s. error: %s" %
-                            (cmd, str(results[cmd_utils.STDERR][0])))
-                else:
-                    dut.adb.pull("%s %s" % (gcda, file_name))
-                gcda_content = open(file_name, "rb").read()
-                gcda_dict[gcda.strip()] = gcda_content
-        self._ClearTargetGcov(dut, serial)
-        return gcda_dict
-
-    def _OutputCoverageReport(self, isGlobal, coverage_report_msg=None):
-        logging.info("Outputing coverage data")
-        timestamp_seconds = str(int(time.time() * 1000000))
-        coverage_report_file_name = "coverage_report_" + timestamp_seconds + ".txt"
-        if self._coverage_report_file_prefix:
-            coverage_report_file_name = "coverage_report_" + self._coverage_report_file_prefix + ".txt"
-
-        coverage_report_file = None
-        if (self._coverage_report_dir):
-            if not os.path.exists(self._coverage_report_dir):
-                os.makedirs(self._coverage_report_dir)
-            coverage_report_file = os.path.join(self._coverage_report_dir,
-                                                coverage_report_file_name)
-        else:
-            coverage_report_file = os.path.join(self.local_coverage_path,
-                                                coverage_report_file_name)
-
-        logging.info("Storing coverage report to: %s", coverage_report_file)
-        if self.web and self.web.enabled:
-            coverage_report_msg = ReportMsg.TestReportMessage()
-            if isGlobal:
-                for c in self.web.report_msg.coverage:
-                    coverage = coverage_report_msg.coverage.add()
-                    coverage.CopyFrom(c)
-            else:
-                for c in self.web.current_test_report_msg.coverage:
-                    coverage = coverage_report_msg.coverage.add()
-                    coverage.CopyFrom(c)
-        if coverage_report_msg is not None:
-            with open(coverage_report_file, "w+") as f:
-                f.write(str(coverage_report_msg))
-
-    def _AutoProcess(self, cov_zip, revision_dict, gcda_dict, isGlobal):
-        """Process coverage data and appends coverage reports to the report message.
-
-        Matches gcno files with gcda files and processes them into a coverage report
-        with references to the original source code used to build the system image.
-        Coverage information is appended as a CoverageReportMessage to the provided
-        report message.
-
-        Git project information is automatically extracted from the build info and
-        the source file name enclosed in each gcno file. Git project names must
-        resemble paths and may differ from the paths to their project root by at
-        most one. If no match is found, then coverage information will not be
-        be processed.
-
-        e.g. if the project path is test/vts, then its project name may be
-             test/vts or <some folder>/test/vts in order to be recognized.
-
-        Args:
-            cov_zip: the ZipFile object containing the gcno coverage artifacts.
-            revision_dict: the dictionary from project name to project version.
-            gcda_dict: the dictionary of gcda basenames to gcda content (binary string)
-            isGlobal: boolean, True if the coverage data is for the entire test, False if only for
-                      the current test case.
-        """
-        checksum_gcno_dict = self._GetChecksumGcnoDict(cov_zip)
-        output_coverage_report = getattr(
-            self, keys.ConfigKeys.IKEY_OUTPUT_COVERAGE_REPORT, False)
-        exclude_coverage_path = getattr(
-            self, keys.ConfigKeys.IKEY_EXCLUDE_COVERAGE_PATH, [])
-        for idx, path in enumerate(exclude_coverage_path):
-            base_name = os.path.basename(path)
-            if base_name and "." not in base_name:
-                path = path if path.endswith("/") else path + "/"
-                exclude_coverage_path[idx] = path
-        exclude_coverage_path.extend(self._DEFAULT_EXCLUDE_PATHS)
-
-        coverage_dict = dict()
-        coverage_report_message = ReportMsg.TestReportMessage()
-
-        for gcda_name in gcda_dict:
-            if GEN_TAG in gcda_name:
-                # skip coverage measurement for intermediate code.
-                logging.warn("Skip for gcda file: %s", gcda_name)
-                continue
-
-            gcda_stream = io.BytesIO(gcda_dict[gcda_name])
-            gcda_file_parser = gcda_parser.GCDAParser(gcda_stream)
-            file_name = gcda_name.rsplit(".", 1)[0]
-
-            if not gcda_file_parser.checksum in checksum_gcno_dict:
-                logging.info("No matching gcno file for gcda: %s", gcda_name)
-                continue
-            gcno_file_parsers = checksum_gcno_dict[gcda_file_parser.checksum]
-            gcno_summary = self._FindGcnoSummary(file_name, gcno_file_parsers)
-            if gcno_summary is None:
-                logging.error("No gcno file found for gcda %s.", gcda_name)
-                continue
-
-            # Process and merge gcno/gcda data
-            try:
-                gcda_file_parser.Parse(gcno_summary)
-            except FileFormatError:
-                logging.error("Error parsing gcda file %s", gcda_name)
-                continue
-
-            coverage_report.GenerateLineCoverageVector(
-                gcno_summary, exclude_coverage_path, coverage_dict)
-
-        for src_file_path in coverage_dict:
-            # Get the git project information
-            # Assumes that the project name and path to the project root are similar
-            revision = None
-            for project_name in revision_dict:
-                # Matches cases when source file root and project name are the same
-                if src_file_path.startswith(str(project_name)):
-                    git_project_name = str(project_name)
-                    git_project_path = str(project_name)
-                    revision = str(revision_dict[project_name])
-                    logging.debug("Source file '%s' matched with project '%s'",
-                                  src_file_path, git_project_name)
-                    break
-
-                parts = os.path.normpath(str(project_name)).split(os.sep, 1)
-                # Matches when project name has an additional prefix before the
-                # project path root.
-                if len(parts) > 1 and src_file_path.startswith(parts[-1]):
-                    git_project_name = str(project_name)
-                    git_project_path = parts[-1]
-                    revision = str(revision_dict[project_name])
-                    logging.debug("Source file '%s' matched with project '%s'",
-                                  src_file_path, git_project_name)
-                    break
-
-            if not revision:
-                logging.info("Could not find git info for %s", src_file_path)
-                continue
-
-            coverage_vec = coverage_dict[src_file_path]
-            total_count, covered_count = coverage_report.GetCoverageStats(
-                coverage_vec)
-            if self.web and self.web.enabled:
-                self.web.AddCoverageReport(coverage_vec, src_file_path,
-                                           git_project_name, git_project_path,
-                                           revision, covered_count,
-                                           total_count, isGlobal)
-            else:
-                coverage = coverage_report_message.coverage.add()
-                coverage.total_line_count = total_count
-                coverage.covered_line_count = covered_count
-                coverage.line_coverage_vector.extend(coverage_vec)
-
-                src_file_path = os.path.relpath(src_file_path,
-                                                git_project_path)
-                coverage.file_path = src_file_path
-                coverage.revision = revision
-                coverage.project_name = git_project_name
-
-        if output_coverage_report:
-            self._OutputCoverageReport(isGlobal, coverage_report_message)
-
-    # TODO: consider to deprecate the manual process.
-    def _ManualProcess(self, cov_zip, revision_dict, gcda_dict, isGlobal):
-        """Process coverage data and appends coverage reports to the report message.
-
-        Opens the gcno files in the cov_zip for the specified modules and matches
-        gcno/gcda files. Then, coverage vectors are generated for each set of matching
-        gcno/gcda files and appended as a CoverageReportMessage to the provided
-        report message. Unlike AutoProcess, coverage information is only processed
-        for the modules explicitly defined in 'modules'.
-
-        Args:
-            cov_zip: the ZipFile object containing the gcno coverage artifacts.
-            revision_dict: the dictionary from project name to project version.
-            gcda_dict: the dictionary of gcda basenames to gcda content (binary string)
-            isGlobal: boolean, True if the coverage data is for the entire test, False if only for
-                      the current test case.
-        """
-        output_coverage_report = getattr(
-            self, keys.ConfigKeys.IKEY_OUTPUT_COVERAGE_REPORT, True)
-        modules = getattr(self, keys.ConfigKeys.IKEY_MODULES, None)
-        covered_modules = set(cov_zip.namelist())
-        for module in modules:
-            if MODULE_NAME not in module or GIT_PROJECT not in module:
-                logging.error(
-                    "Coverage module must specify name and git project: %s",
-                    module)
-                continue
-            project = module[GIT_PROJECT]
-            if PATH not in project or NAME not in project:
-                logging.error("Project name and path not specified: %s",
-                              project)
-                continue
-
-            name = str(module[MODULE_NAME]) + COVERAGE_SUFFIX
-            git_project = str(project[NAME])
-            git_project_path = str(project[PATH])
-
-            if name not in covered_modules:
-                logging.error("No coverage information for module %s", name)
-                continue
-            if git_project not in revision_dict:
-                logging.error(
-                    "Git project not present in device revision dict: %s",
-                    git_project)
-                continue
-
-            revision = str(revision_dict[git_project])
-            archive = archive_parser.Archive(cov_zip.open(name).read())
-            try:
-                archive.Parse()
-            except ValueError:
-                logging.error("Archive could not be parsed: %s", name)
-                continue
-
-            for gcno_file_path in archive.files:
-                file_name_path = gcno_file_path.rsplit(".", 1)[0]
-                file_name = os.path.basename(file_name_path)
-                gcno_content = archive.files[gcno_file_path]
-                gcno_stream = io.BytesIO(gcno_content)
-                try:
-                    gcno_summary = gcno_parser.GCNOParser(gcno_stream).Parse()
-                except FileFormatError:
-                    logging.error("Error parsing gcno file %s", gcno_file_path)
-                    continue
-                src_file_path = None
-
-                # Match gcno file with gcda file
-                gcda_name = file_name + GCDA_SUFFIX
-                if gcda_name not in gcda_dict:
-                    logging.error("No gcda file found %s.", gcda_name)
-                    continue
-
-                src_file_path = self._ExtractSourceName(
-                    gcno_summary, file_name)
-
-                if not src_file_path:
-                    logging.error("No source file found for %s.",
-                                  gcno_file_path)
-                    continue
-
-                # Process and merge gcno/gcda data
-                gcda_content = gcda_dict[gcda_name]
-                gcda_stream = io.BytesIO(gcda_content)
-                try:
-                    gcda_parser.GCDAParser(gcda_stream).Parse(gcno_summary)
-                except FileFormatError:
-                    logging.error("Error parsing gcda file %s", gcda_content)
-                    continue
-
-                if self.web and self.web.enabled:
-                    coverage_vec = coverage_report.GenerateLineCoverageVector(
-                        src_file_path, gcno_summary)
-                    total_count, covered_count = coverage_report.GetCoverageStats(
-                        coverage_vec)
-                    self.web.AddCoverageReport(coverage_vec, src_file_path,
-                                               git_project, git_project_path,
-                                               revision, covered_count,
-                                               total_count, isGlobal)
-
-        if output_coverage_report:
-            self._OutputCoverageReport(isGlobal)
-
-    def SetCoverageData(self, dut=None, serial=None, isGlobal=False):
-        """Sets and processes coverage data.
-
-        Organizes coverage data and processes it into a coverage report in the
-        current test case
-
-        Requires feature to be enabled; no-op otherwise.
-
-        Args:
-            dut:  the device object for which to pull coverage data
-            isGlobal: True if the coverage data is for the entire test, False if
-                      if the coverage data is just for the current test case.
-        """
-        if not self.enabled:
-            return
-
-        if serial is None:
-            serial = "default" if dut is None else dut.adb.shell(
-                "getprop ro.serialno").strip()
-
-        if not serial in self._device_resource_dict:
-            logging.error("Invalid device provided: %s", serial)
-            return
-
-        resource_path = self._device_resource_dict[serial]
-        if not resource_path:
-            logging.error("Coverage resource path not found.")
-            return
-
-        gcda_dict = self._GetGcdaDict(dut, serial)
-        logging.debug("Coverage file paths %s", str([fp for fp in gcda_dict]))
-
-        cov_zip = zipfile.ZipFile(os.path.join(resource_path, _GCOV_ZIP))
-
-        revision_dict = json.load(
-            open(os.path.join(resource_path, _BUILD_INFO)))[_REPO_DICT]
-
-        if not hasattr(self, keys.ConfigKeys.IKEY_MODULES):
-            # auto-process coverage data
-            self._AutoProcess(cov_zip, revision_dict, gcda_dict, isGlobal)
-        else:
-            # explicitly process coverage data for the specified modules
-            self._ManualProcess(cov_zip, revision_dict, gcda_dict, isGlobal)
-
-        # cleanup the downloaded gcda files.
-        logging.debug("Cleaning up gcda files.")
-        files = os.listdir(self.local_coverage_path)
-        for item in files:
-            if item.endswith(".gcda"):
-                os.remove(os.path.join(self.local_coverage_path, item))
-
-    def SetHalNames(self, names=[]):
-        """Sets the HAL names for which to process coverage.
-
-        Args:
-            names: list of strings, names of hal (e.g. android.hardware.light@2.0)
-        """
-        self._hal_names = list(names)
-
-    def SetCoverageReportFilePrefix(self, prefix):
-        """Sets the prefix for outputting the coverage report file.
-
-        Args:
-            prefix: strings, prefix of the coverage report file.
-        """
-        self._coverage_report_file_prefix = prefix
-
-    def SetCoverageReportDirectory(self, corverage_report_dir):
-        """Sets the path for storing the coverage report file.
-
-        Args:
-            corverage_report_dir: strings, dir to store the coverage report file.
-        """
-        self._coverage_report_dir = corverage_report_dir
-
-    def _ExecuteOneAdbShellCommand(self, dut, serial, cmd):
-        """Helper method to execute a shell command and return results.
-
-        Args:
-            dut: the device under test.
-            cmd: string, command to execute.
-        Returns:
-            stdout result of the command, None if command fails.
-        """
-        if dut is None:
-            results = cmd_utils.ExecuteShellCommand("adb -s %s shell %s" %
-                                                    (serial, cmd))
-            if (results[cmd_utils.EXIT_CODE][0]):
-                logging.error("Fail to execute command: %s. error: %s" %
-                              (cmd, str(results[cmd_utils.STDERR][0])))
-                return None
-            else:
-                return results[cmd_utils.STDOUT][0]
-        else:
-            try:
-                return dut.adb.shell(cmd)
-            except AdbError as e:
-                logging.warn("Fail to execute command: %s. error: %s" %
-                             (cmd, str(e)))
-                return None
-
-
-if __name__ == '__main__':
-    """ Tools to process coverage data.
-
-    Usage:
-      python coverage_utils.py operation [--serial=device_serial_number]
-      [--report_prefix=prefix_of_coverage_report]
-
-    Example:
-      python coverage_utils.py init_coverage
-      python coverage_utils.py get_coverage --serial HT7821A00243
-      python coverage_utils.py get_coverage --serial HT7821A00243 --report_prefix=test
-    """
-    logging.basicConfig(level=logging.INFO)
-    parser = argparse.ArgumentParser(description="Coverage process tool.")
-    parser.add_argument(
-        "--report_prefix",
-        dest="report_prefix",
-        required=False,
-        help="Prefix of the coverage report.")
-    parser.add_argument(
-        "--report_path",
-        dest="report_path",
-        required=False,
-        help="directory to store the coverage reports.")
-    parser.add_argument(
-        "--serial", dest="serial", required=True, help="Device serial number.")
-    parser.add_argument(
-        "--gcov_rescource_path",
-        dest="gcov_rescource_path",
-        required=True,
-        help="Directory that stores gcov resource files.")
-    parser.add_argument(
-        "operation",
-        help=
-        "Operation for processing coverage data, e.g. 'init_coverage', get_coverage'"
-    )
-    args = parser.parse_args()
-
-    if args.operation != "init_coverage" and args.operation != "get_coverage":
-        print "Unsupported operation. Exiting..."
-        sys.exit(1)
-    user_params = {
-        keys.ConfigKeys.IKEY_ENABLE_COVERAGE:
-        True,
-        keys.ConfigKeys.IKEY_ANDROID_DEVICE: [{
-            keys.ConfigKeys.IKEY_SERIAL:
-            args.serial,
-            keys.ConfigKeys.IKEY_GCOV_RESOURCES_PATH:
-            args.gcov_rescource_path,
-        }],
-        keys.ConfigKeys.IKEY_OUTPUT_COVERAGE_REPORT:
-        True,
-        keys.ConfigKeys.IKEY_GLOBAL_COVERAGE:
-        True
-    }
-    coverage = CoverageFeature(user_params)
-    if args.operation == "init_coverage":
-        coverage.InitializeDeviceCoverage(serial=args.serial)
-    elif args.operation == "get_coverage":
-        if args.report_prefix:
-            coverage.SetCoverageReportFilePrefix(args.report_prefix)
-        if args.report_path:
-            coverage.SetCoverageReportDirectory(args.report_path)
-        coverage.SetCoverageData(serial=args.serial, isGlobal=True)
diff --git a/utils/python/coverage/file_summary.py b/utils/python/coverage/file_summary.py
deleted file mode 100644
index 211188a..0000000
--- a/utils/python/coverage/file_summary.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-
-class FileSummary(object):
-    """Summarizes structure and coverage information from GCC output.
-
-    Represents the data in .gcno and .gcda files.
-
-    Attributes:
-    functions: Dictionary of FunctionSummary objects for each function described
-        in a GCNO file (key: integer ident, value: FunctionSummary object)
-    """
-
-    def __init__(self):
-        """Inits the object with an empty list in its functions attribute.
-        """
-        self.functions = {}
-
-    def __str__(self):
-        """Serializes the summary as a string.
-
-        Returns:
-            String representation of the functions, blocks, arcs, and lines.
-        """
-        output = 'Coverage Summary:\r\n'
-        for ident in self.functions:
-            output += str(self.functions[ident])
-        return output
diff --git a/utils/python/coverage/function_summary.py b/utils/python/coverage/function_summary.py
deleted file mode 100644
index 3cf89ea..0000000
--- a/utils/python/coverage/function_summary.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-
-class FunctionSummary(object):
-    """Summarizes a function and its blocks from .gcno file.
-
-    Attributes:
-        blocks: list of BlockSummary objects for each block in the function.
-        ident: integer function identifier.
-        name: function name.
-        src_file_name: name of source file containing the function.
-        first_line_number: integer line number at which the function begins in
-            srcFile.
-    """
-
-    def __init__(self, ident, name, src_file_name, first_line_number):
-        """Inits the function summary with provided values.
-
-        Stores the identification string, name, source file name, and
-        first line number in the object attributes. Initializes the block
-        attribute to the empty list.
-
-        Args:
-            ident: integer function identifier.
-            name: function name.
-            src_file_name: name of source file containing the function.
-            first_line_number: integer line number at which the function begins in
-              the source file.
-        """
-        self.blocks = []
-        self.ident = ident
-        self.name = name
-        self.src_file_name = src_file_name
-        self.first_line_number = first_line_number
-
-    def Resolve(self):
-        """Resolves the block and arc counts.
-
-        Using the edges that were resolved by the GCDA file,
-        counts are resolved in the unresolved arcs. Then, block
-        counts are resolved by summing the counts along arcs entering
-        the block.
-
-        Returns:
-            True if the counts could be resolved and False otherwise.
-        """
-
-        unresolved_arcs = []
-        for block in self.blocks:
-            for arc in block.exit_arcs:
-                if not arc.resolved:
-                    unresolved_arcs.append(arc)
-
-        index = 0
-        prev_length = len(unresolved_arcs) + 1
-        # Resolve the arc counts
-        while len(unresolved_arcs) > 0:
-            index = index % len(unresolved_arcs)
-            if index == 0 and len(unresolved_arcs) == prev_length:
-                return False
-            else:
-                prev_length = len(unresolved_arcs)
-            arc = unresolved_arcs[index]
-            if arc.Resolve():
-                unresolved_arcs.remove(arc)
-            else:
-                index = index + 1
-
-        # Resolve the block counts
-        for block in self.blocks:
-            if len(block.entry_arcs):
-                block.count = sum(arc.count for arc in block.entry_arcs)
-            else:
-                block.count = sum(arc.count for arc in block.exit_arcs)
-
-        return True
-
-    def __str__(self):
-        """Serializes the function summary as a string.
-
-        Returns:
-            String representation of the functions and its blocks.
-        """
-        output = ('Function:  %s : %s\r\n\tFirst Line Number:%i\r\n' %
-                  (self.src_file_name, self.name, self.first_line_number))
-        for b in self.blocks:
-            output += str(b)
-        return output
diff --git a/utils/python/coverage/function_summary_test.py b/utils/python/coverage/function_summary_test.py
deleted file mode 100644
index 16ea4db..0000000
--- a/utils/python/coverage/function_summary_test.py
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2016 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.
-#
-
-import os
-import unittest
-
-from vts.utils.python.coverage import arc_summary
-from vts.utils.python.coverage import block_summary
-from vts.utils.python.coverage import function_summary
-
-
-class FunctionSummaryTest(unittest.TestCase):
-    """Tests for FunctionSummary of vts.utils.python.coverage.
-    """
-
-    def setUp(self):
-        """Creates a function summary and a chain of blocks.
-
-        Creates an arc between adjacent blocks. All arcs are left with default
-        values (unresolved, count of 0).
-        """
-        self.n = 10
-        self.count = 5
-        self.function_summary = function_summary.FunctionSummary(0, 'test',
-                                                                 'test.c', 0)
-        self.function_summary.blocks = [block_summary.BlockSummary(i, 0)
-                                        for i in range(self.n)]
-        self.arcs = []
-        for i in range(1, self.n):
-            arc = arc_summary.ArcSummary(self.function_summary.blocks[i - 1],
-                                         self.function_summary.blocks[i], 0)
-            self.function_summary.blocks[i - 1].exit_arcs.append(arc)
-            self.function_summary.blocks[i].entry_arcs.append(arc)
-            self.arcs.append(arc)
-
-    def testResolveChainStart(self):
-        """Tests for correct resolution in a long chain.
-
-        Test resolution for the case when there is a chain of unresolved arcs
-        after a resolved arc.
-        """
-        self.arcs[0].resolved = True
-        self.arcs[0].count = self.count
-
-        self.function_summary.Resolve()
-        for arc in self.arcs:
-            self.assertTrue(arc.resolved)
-            self.assertEqual(self.count, arc.count)
-            self.assertEqual(self.count, arc.src_block.count)
-            self.assertEqual(self.count, arc.dst_block.count)
-
-    def testResolveChainEnd(self):
-        """Tests for correct resolution in a long chain.
-
-        Test resolution for the case when there is a chain of unresolved arcs
-        before a resolved arc.
-        """
-        self.arcs[-1].resolved = True
-        self.arcs[-1].count = self.count
-
-        self.function_summary.Resolve()
-        for arc in self.arcs:
-            self.assertTrue(arc.resolved)
-            self.assertEqual(self.count, arc.count)
-            self.assertEqual(self.count, arc.src_block.count)
-            self.assertEqual(self.count, arc.dst_block.count)
-
-    def testResolveFailure(self):
-        """Tests for failure when no progress can be made.
-
-        Test that Resolve() returns False when there is not enough information
-        to resolve any arcs.
-        """
-        self.assertFalse(self.function_summary.Resolve())
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/utils/python/coverage/gcda_parser.py b/utils/python/coverage/gcda_parser.py
deleted file mode 100644
index b2dbc3c..0000000
--- a/utils/python/coverage/gcda_parser.py
+++ /dev/null
@@ -1,192 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-"""Parses the contents of a GCDA file generated by the GCC compiler.
-
-The parse() function updates a summary object, which was created by
-the GCNO parser, and includes coverage information along arcs and at
-code blocks.
-
-
-    Typical usage example:
-
-    parse(file_name, file_summary)
-"""
-
-import struct
-import sys
-
-from vts.utils.python.coverage import parser
-from vts.utils.python.coverage import gcno_parser
-
-class GCDAParser(parser.GcovStreamParserUtil):
-    """Parser object class stores stateful information for parsing GCDA files.
-
-    Stores the file stream and a FileSummary object as it is updated.
-
-    Attributes:
-        checksum: The checksum (int) of the file
-        file_summary: The FileSummary object describing the source file
-        format: Character denoting the endianness of the file
-        stream: File stream object for a GCDA file
-    """
-
-    MAGIC = 0x67636461
-    TAG_FUNCTION = 0x01000000
-    TAG_COUNTER = 0x01a10000
-    TAG_OBJECT = 0xa1000000
-    TAG_PROGRAM = 0xa3000000
-
-    def __init__(self, stream):
-        """Inits the parser with the input stream and default values.
-
-        The byte order is set by default to little endian and the summary file
-        must be provided from the output of the GCNOparser.
-
-        Args:
-            stream: An input binary file stream to a .gcno file
-        """
-        self._file_summary = None
-        super(GCDAParser, self).__init__(stream, self.MAGIC)
-
-    @property
-    def file_summary(self):
-        """Gets the FileSummary object where coverage data is stored.
-
-        Returns:
-            A FileSummary object.
-        """
-        return self._file_summary
-
-    @file_summary.setter
-    def file_summary(self, file_summary):
-        """Sets the FileSummary object in which to store coverage data.
-
-        Args:
-            file_summary: A FileSummary object from a processed gcno file
-        """
-        self._file_summary = file_summary
-
-    def Parse(self, file_summary):
-        """Runs the parser on the file opened in the stream attribute.
-
-        Reads coverage information from the GCDA file stream and resolves
-        block and edge weights.
-
-        Returns:
-            FileSummary object representing the coverage for functions, blocks,
-            arcs, and lines in the opened GCNO file.
-
-        Raises:
-            parser.FileFormatError: invalid file format or invalid counts.
-        """
-        self.file_summary = file_summary
-        func = None
-
-        while True:
-            tag = str()
-
-            try:
-                while True:
-                    tag = self.ReadInt()
-                    if (tag == self.TAG_FUNCTION or tag == self.TAG_COUNTER or
-                            tag == self.TAG_OBJECT or tag == self.TAG_PROGRAM):
-                        break
-                length = self.ReadInt()
-            except parser.FileFormatError:
-                return self.file_summary  #  end of file reached
-
-            if tag == self.TAG_FUNCTION:
-                func = self.ReadFunction(length)
-            elif tag == self.TAG_COUNTER:
-                self.ReadCounts(func)
-                if not func.Resolve():
-                    raise parser.FileFormatError(
-                        "Corrupt file: Counts could not be resolved.")
-            elif tag == self.TAG_OBJECT:
-                pass
-            elif tag == self.TAG_PROGRAM:
-                self.ReadInt()  #  checksum
-                for i in range(length - 1):
-                    self.ReadInt()
-
-    def ReadFunction(self, length):
-        """Reads a function header from the stream.
-
-        Reads information about a function from the gcda file stream and
-        returns the function.
-
-        Args:
-            func: the function for which coverage information will be read.
-
-        Raises:
-            parser.FileFormatError: Corrupt file.
-        """
-        ident = self.ReadInt()
-        func = self.file_summary.functions[ident]
-        checksum = self.ReadInt()
-        words_read = 3
-        if int(self.version[1]) > 4:
-            self.ReadInt()
-            words_read = 4
-
-        if words_read < length:
-            gcda_name = self.ReadString()
-
-        return func
-
-    def ReadCounts(self, func):
-        """Reads arc counts from the stream.
-
-        Reads counts from the gcda file stream for arcs that are not
-        fake and are not in the tree. Updates their counts and marks them
-        as having resolved counts.
-
-        Args:
-            func: FunctionSummary for which arc counts will be read.
-        """
-        for block in func.blocks:
-            for arc in block.exit_arcs:
-                if not arc.fake and not arc.on_tree:
-                    count = self.ReadInt64()
-                    arc.count = count
-                    arc.resolved = True
-
-
-def ParseGcdaFile(file_name, file_summary):
-    """Parses the .gcno file specified by the input.
-
-    Reads the .gcno file specified and parses the information describing
-    basic blocks, functions, and arcs.
-
-    Args:
-        file_name: A string file path to a .gcno file
-        file_summary: The summary from a parsed gcno file
-
-    Returns:
-        A summary object containing information about the coverage for each
-        block in each function.
-    """
-
-    with open(file_name, 'rb') as stream:
-        return GCDAParser(stream).Parse(file_summary)
-
-
-if __name__ == '__main__':
-    if len(sys.argv) != 2:
-        print('usage: gcda_parser.py [gcda file name] [gcno file name]')
-    else:
-        file_summary = gcno_parser.ParseGcnoFile(sys.argv[2])
-        print(str(ParseGcdaFile(sys.argv[1], file_summary)))
diff --git a/utils/python/coverage/gcda_parser_test.py b/utils/python/coverage/gcda_parser_test.py
deleted file mode 100644
index df1b4b0..0000000
--- a/utils/python/coverage/gcda_parser_test.py
+++ /dev/null
@@ -1,144 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2016 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.
-#
-import os
-import unittest
-
-from vts.utils.python.coverage import arc_summary
-from vts.utils.python.coverage import block_summary
-from vts.utils.python.coverage import file_summary
-from vts.utils.python.coverage import function_summary
-from vts.utils.python.coverage import gcda_parser
-from vts.utils.python.coverage import gcno_parser
-from vts.utils.python.coverage.parser_test import MockStream
-
-
-class GCDAParserTest(unittest.TestCase):
-    """Tests for GCDA parser of vts.utils.python.coverage.
-    """
-
-    GOLDEN_GCNO_PATH = 'testdata/sample.gcno'
-    GOLDEN_GCDA_PATH = 'testdata/sample.gcda'
-
-    def setUp(self):
-        """Creates a stream for each test.
-      """
-        self.stream = MockStream(gcda_parser.GCDAParser.MAGIC)
-
-    def testReadFunction(self):
-        """Verifies that the correct function is read and returned.
-        """
-        ident = 100
-        checksum = 0
-        fs = file_summary.FileSummary()
-        func = function_summary.FunctionSummary(ident, 'test', 'test.c', 0)
-        fs.functions[ident] = func
-        self.stream = MockStream.concat_int(self.stream, ident)
-        self.stream = MockStream.concat_int(self.stream, 0)
-        self.stream = MockStream.concat_int(self.stream, 0)
-        self.stream = MockStream.concat_string(self.stream, 'test')
-        length = 5
-        parser = gcda_parser.GCDAParser(self.stream)
-        parser.file_summary = fs
-        func = parser.ReadFunction(5)
-        assert (func.ident == ident)
-
-    def testReadCountsNormal(self):
-        """Verifies that counts are read correctly.
-
-        Verifies that arcs are marked as resolved and count is correct.
-        """
-        n = 5
-        fs = file_summary.FileSummary()
-        func = function_summary.FunctionSummary(0, 'test', 'test.c', 0)
-        blocks = [block_summary.BlockSummary(i, 0) for i in range(n)]
-        func.blocks = blocks
-        fs.functions[func.ident] = func
-        for i in range(1, n):
-            arc = arc_summary.ArcSummary(blocks[0], blocks[i], 0)
-            blocks[0].exit_arcs.append(arc)
-            blocks[i].entry_arcs.append(arc)
-            self.stream = MockStream.concat_int64(self.stream, i)
-        parser = gcda_parser.GCDAParser(self.stream)
-        parser.file_summary = fs
-        parser.ReadCounts(func)
-        for i, arc in zip(range(1, n), blocks[0].exit_arcs):
-            self.assertEqual(i, arc.count)
-            self.assertTrue(arc.resolved)
-
-    def testReadCountsFakeOrOnTree(self):
-        """Verifies that counts are read correctly when there are skipped arcs.
-
-        Verifies that the fake arc and the arc on the tree are skipped while other
-        arcs are read and resolved correctly.
-        """
-        n = 10
-        fs = file_summary.FileSummary()
-        func = function_summary.FunctionSummary(0, 'test', 'test.c', 0)
-        blocks = [block_summary.BlockSummary(i, 0) for i in range(n)]
-        func.blocks = blocks
-        fs.functions[func.ident] = func
-
-        arc = arc_summary.ArcSummary(blocks[0], blocks[1],
-                                     arc_summary.ArcSummary.GCOV_ARC_FAKE)
-        blocks[0].exit_arcs.append(arc)
-        blocks[1].entry_arcs.append(arc)
-
-        arc = arc_summary.ArcSummary(blocks[0], blocks[2],
-                                     arc_summary.ArcSummary.GCOV_ARC_ON_TREE)
-        blocks[0].exit_arcs.append(arc)
-        blocks[2].entry_arcs.append(arc)
-
-        for i in range(3, n):
-            arc = arc_summary.ArcSummary(blocks[0], blocks[i], 0)
-            blocks[0].exit_arcs.append(arc)
-            blocks[i].entry_arcs.append(arc)
-            self.stream = MockStream.concat_int64(self.stream, i)
-
-        parser = gcda_parser.GCDAParser(self.stream)
-        parser.file_summary = fs
-        parser.ReadCounts(func)
-        self.assertFalse(blocks[0].exit_arcs[0].resolved)
-        self.assertFalse(blocks[0].exit_arcs[1].resolved)
-        for i, arc in zip(range(3, n), blocks[0].exit_arcs[2:]):
-            self.assertEqual(i, arc.count)
-            self.assertTrue(arc.resolved)
-
-    def testSampleFile(self):
-        """Asserts correct parsing of sample GCDA file.
-
-        Verifies the block coverage counts for each function.
-        """
-        dir_path = os.path.dirname(os.path.realpath(__file__))
-        gcno_path = os.path.join(dir_path, self.GOLDEN_GCNO_PATH)
-        gcda_path = os.path.join(dir_path, self.GOLDEN_GCDA_PATH)
-        summary = gcno_parser.ParseGcnoFile(gcno_path)
-        gcda_parser.ParseGcdaFile(gcda_path, summary)
-        # Function: main
-        expected_list = [2, 0, 2, 2, 2, 0, 2, 2, 500, 502, 2, 2]
-        for index, expected in zip(range(len(expected_list)), expected_list):
-            self.assertEqual(summary.functions[3].blocks[index].count,
-                             expected)
-
-        # Function: testFunctionName
-        expected_list = [2, 2, 2, 2, 2]
-        for index, expected in zip(range(len(expected_list)), expected_list):
-            self.assertEqual(summary.functions[4].blocks[index].count,
-                             expected)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/utils/python/coverage/gcno_parser.py b/utils/python/coverage/gcno_parser.py
deleted file mode 100644
index 62bafd9..0000000
--- a/utils/python/coverage/gcno_parser.py
+++ /dev/null
@@ -1,242 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-"""Parses the contents of a GCNO file generated by the GCC compiler.
-
-The parse() function returns a FileSummary object, which
-contains descriptions of all functions in the parsed .gcno file. Each
-FunctionSummary object describes the code blocks within each function,
-the line numbers associated within each block, and the arcs exiting/entering
-each block.
-
-
-    Typical usage example:
-
-    summary = parse(file_name)
-"""
-
-import math
-import struct
-import sys
-
-from vts.utils.python.coverage import arc_summary
-from vts.utils.python.coverage import block_summary
-from vts.utils.python.coverage import file_summary
-from vts.utils.python.coverage import function_summary
-from vts.utils.python.coverage import parser
-
-
-class GCNOParser(parser.GcovStreamParserUtil):
-    """Parser object class stores stateful information for parsing GCNO file.
-
-    Stores the file stream and summary object as it is updated.
-
-    Attributes:
-        checksum: The checksum (int) of the file
-        file_summary: The FileSummary object describing the GCNO file
-        format: Character denoting the endianness of the file
-        parsed: True if the content has been parsed, False otherwise
-        stream: File stream object for a GCNO file
-        version: The (integer) version of the GCNO file
-    """
-
-    MAGIC = 0x67636e6f
-    TAG_FUNCTION = 0x01000000
-    TAG_BLOCKS = 0x01410000
-    TAG_ARCS = 0x01430000
-    TAG_LINES = 0x01450000
-    BYTES_IN_WORD = 4
-    HEADER_LENGTH = 3  #  number of words in a section header
-
-    def __init__(self, stream):
-        """Inits the parser with the input stream and default values.
-
-        The byte order is set by default to little endian and the summary file
-        is instantiated with an empty FileSummary object.
-
-        Args:
-            stream: An input binary file stream to a .gcno file
-        """
-        super(GCNOParser, self).__init__(stream, self.MAGIC)
-        self.file_summary = file_summary.FileSummary()
-        self.parsed = False
-
-    def Parse(self):
-        """Runs the parser on the file opened in the stream attribute.
-
-        Reads the binary file and extracts functions, blocks, arcs, and
-        lines. Information is stored the summary attribute.
-
-        Returns:
-            FileSummary object representing the functions, blocks, arcs,
-            and lines in the opened GCNO file.
-
-        Raises:
-            parser.FileFormatError: invalid file format.
-        """
-        if self.parsed:
-            return self.file_summary
-
-        func = None
-
-        while True:
-            tag = str()
-
-            try:
-                while True:
-                    tag = self.ReadInt()
-                    if (tag == self.TAG_FUNCTION or tag == self.TAG_BLOCKS or
-                            tag == self.TAG_ARCS or tag == self.TAG_LINES):
-                        break
-                length = self.ReadInt()
-            except parser.FileFormatError:
-                if not func:
-                    raise parser.FileFormatError("Invalid file.")
-                self.file_summary.functions[func.ident] = func
-                self.parsed = True
-                return self.file_summary  #  end of file reached
-
-            if tag == self.TAG_FUNCTION:
-                if func:
-                    self.file_summary.functions[func.ident] = func
-                func = self.ReadFunction()
-
-            elif tag == self.TAG_BLOCKS:
-                self.ReadBlocks(length, func)
-
-            elif tag == self.TAG_ARCS:
-                self.ReadArcs(length, func)
-
-            elif tag == self.TAG_LINES:
-                self.ReadLines(length, func)
-
-    def ReadFunction(self):
-        """Reads and returns a function from the stream.
-
-        Reads information about a function from the gcno file stream and
-        returns a summary object.
-
-        Returns:
-            FunctionSummary object containing the function name, source file,
-            and first line number.
-
-        Raises:
-            parser.FileFormatError: Function could not be read.
-        """
-        ident = self.ReadInt()
-        self.ReadInt()  #  line number checksum
-        if int(self.version[1]) > 4:
-            self.ReadInt()  #  configuration checksum
-        name = self.ReadString()
-        source_file_name = self.ReadString()
-        first_line_number = self.ReadInt()
-        return function_summary.FunctionSummary(ident, name, source_file_name,
-                                                first_line_number)
-
-    def ReadBlocks(self, length, func):
-        """Reads the basic block information from the stream.
-
-        Reads information about the basic blocks from the gcno file
-        stream and updates the specified function.
-
-        Args:
-            length: number of blocks to read
-            func: FunctionSummary object for the blocks' parent function
-
-        Raises:
-            parser.FileFormatError: Blocks could not be read. Corrupt file.
-        """
-
-        blocks = []
-        for _ in range(length):
-            block_flag = self.ReadInt()
-            block = block_summary.BlockSummary(len(blocks), block_flag)
-            blocks.append(block)
-        func.blocks.extend(blocks)
-
-    def ReadArcs(self, length, func):
-        """Reads the arcs from the stream.
-
-        Parses the arcs from the gcno file and updates the input
-        function summary with arc information.
-
-        Args:
-            length: represents the number of bytes to read
-            func: FunctionSummary object for the arcs' parent fuction
-
-        Raises:
-            parser.FileFormatError: Arcs could not be read. Corrupt file.
-        """
-
-        src_block_index = self.ReadInt()
-        src_block = func.blocks[src_block_index]
-        n_arcs = (length - 1) / 2
-        arcs = []
-        for _ in range(n_arcs):
-            dst_block_index = self.ReadInt()
-            dst_block = func.blocks[dst_block_index]
-            flag = self.ReadInt()
-            arc = arc_summary.ArcSummary(src_block, dst_block, flag)
-            src_block.exit_arcs.append(arc)
-            dst_block.entry_arcs.append(arc)
-
-    def ReadLines(self, length, func):
-        """Reads the line information from the stream.
-
-        Parses the lines from the gcno file and updates the input
-        function summary with line information.
-
-        Args:
-            length: represents the number of bytes to read
-            func: FunctionSummary object for the lines' parent fuction
-
-        Raises:
-            parser.FileFormatError: Lines could not be read. Corrupt file.
-        """
-
-        block_number = self.ReadInt()
-        self.ReadInt()
-        lines = []
-        src = self.ReadString()  #  source file name
-        src_length = int(math.ceil(len(src) * 1.0 / self.BYTES_IN_WORD)) + 1
-        for i in range(length - src_length - self.HEADER_LENGTH):
-            line = self.ReadInt()
-            if line:
-                lines.append(line)
-        func.blocks[block_number].lines = lines
-
-
-def ParseGcnoFile(file_name):
-    """Parses the .gcno file specified by the input.
-
-    Reads the .gcno file specified and parses the information describing
-    basic blocks, functions, and arcs.
-
-    Args:
-        file_name: A string file path to a .gcno file
-
-    Returns:
-        A FileSummary object containing information about all of the
-        fuctions, blocks, and arcs in the .gcno file.
-    """
-
-    with open(file_name, 'rb') as stream:
-        return GCNOParser(stream).Parse()
-
-if __name__ == '__main__':
-    if len(sys.argv) < 3 or sys.argv[1] != '-f':
-        print('usage: gcno_parser.py -f [file name]')
-    else:
-        print(str(ParseGcnoFile(sys.argv[2])))
diff --git a/utils/python/coverage/gcno_parser_test.py b/utils/python/coverage/gcno_parser_test.py
deleted file mode 100644
index 9918817..0000000
--- a/utils/python/coverage/gcno_parser_test.py
+++ /dev/null
@@ -1,219 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2016 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.
-#
-
-import math
-import os
-import struct
-import unittest
-
-from vts.utils.python.coverage import arc_summary
-from vts.utils.python.coverage import block_summary
-from vts.utils.python.coverage import function_summary
-from vts.utils.python.coverage import gcno_parser
-from vts.utils.python.coverage.parser_test import MockStream
-
-
-class GCNOParserTest(unittest.TestCase):
-    """Tests for GCNO parser of vts.utils.python.coverage.
-
-    Ensures error handling, byte order detection, and correct
-    parsing of functions, blocks, arcs, and lines.
-    """
-
-    GOLDEN_GCNO_PATH = 'testdata/sample.gcno'
-
-    def setUp(self):
-        """Creates a stream for each test.
-        """
-        self.stream = MockStream()
-
-    def testReadFunction(self):
-        """Asserts that the function is read correctly.
-
-        Verifies that ident, name, source file name,
-        and first line number are all read correctly.
-        """
-        ident = 102010
-        self.stream = MockStream.concat_int(self.stream, ident)
-        self.stream = MockStream.concat_int(self.stream, 0)
-        self.stream = MockStream.concat_int(self.stream, 0)
-        name = "TestFunction"
-        src_file_name = "TestSouceFile.c"
-        first_line_number = 102
-        self.stream = MockStream.concat_string(self.stream, name)
-        self.stream = MockStream.concat_string(self.stream, src_file_name)
-        self.stream = MockStream.concat_int(self.stream, first_line_number)
-        parser = gcno_parser.GCNOParser(self.stream)
-        summary = parser.ReadFunction()
-        self.assertEqual(name, summary.name)
-        self.assertEqual(ident, summary.ident)
-        self.assertEqual(src_file_name, summary.src_file_name)
-        self.assertEqual(first_line_number, summary.first_line_number)
-
-    def testReadBlocks(self):
-        """Asserts that blocks are correctly read from the stream.
-
-        Tests correct values for flag and index.
-        """
-        n_blocks = 10
-        func = function_summary.FunctionSummary(0, "func", "src.c", 1)
-        for i in range(n_blocks):
-            self.stream = MockStream.concat_int(self.stream, 3 * i)
-        parser = gcno_parser.GCNOParser(self.stream)
-        parser.ReadBlocks(n_blocks, func)
-        self.assertEqual(len(func.blocks), n_blocks)
-        for i in range(n_blocks):
-            self.assertEqual(func.blocks[i].flag, 3 * i)
-            self.assertEqual(func.blocks[i].index, i)
-
-    def testReadArcsNormal(self):
-        """Asserts that arcs are correctly read from the stream.
-
-        Does not test the use of flags. Validates that arcs are
-        created in both blocks and the source/destination are
-        correct for each.
-        """
-        n_blocks = 50
-        func = function_summary.FunctionSummary(0, "func", "src.c", 1)
-        func.blocks = [block_summary.BlockSummary(i, 3 * i)
-                       for i in range(n_blocks)]
-        src_block_index = 0
-        skip = 2
-        self.stream = MockStream.concat_int(self.stream, src_block_index)
-        for i in range(src_block_index + 1, n_blocks, skip):
-            self.stream = MockStream.concat_int(self.stream, i)
-            self.stream = MockStream.concat_int(
-                self.stream, 0)  #  no flag applied to the arc
-        parser = gcno_parser.GCNOParser(self.stream)
-        n_arcs = len(range(src_block_index + 1, n_blocks, skip))
-        parser.ReadArcs(n_arcs * 2 + 1, func)
-        j = 0
-        for i in range(src_block_index + 1, n_blocks, skip):
-            self.assertEqual(
-                func.blocks[src_block_index].exit_arcs[j].src_block.index,
-                src_block_index)
-            self.assertEqual(
-                func.blocks[src_block_index].exit_arcs[j].dst_block.index, i)
-            self.assertEqual(func.blocks[i].entry_arcs[0].src_block.index,
-                             src_block_index)
-            self.assertEqual(func.blocks[i].entry_arcs[0].dst_block.index, i)
-            j += 1
-
-    def testReadArcFlags(self):
-        """Asserts that arc flags are correctly interpreted.
-        """
-        n_blocks = 5
-        func = function_summary.FunctionSummary(0, "func", "src.c", 1)
-        func.blocks = [block_summary.BlockSummary(i, 3 * i)
-                       for i in range(n_blocks)]
-        self.stream = MockStream.concat_int(self.stream,
-                                            0)  #  source block index
-
-        self.stream = MockStream.concat_int(self.stream, 1)  #  normal arc
-        self.stream = MockStream.concat_int(self.stream, 0)
-
-        self.stream = MockStream.concat_int(self.stream, 2)  #  on-tree arc
-        self.stream = MockStream.concat_int(
-            self.stream, arc_summary.ArcSummary.GCOV_ARC_ON_TREE)
-
-        self.stream = MockStream.concat_int(self.stream, 3)  #  fake arc
-        self.stream = MockStream.concat_int(
-            self.stream, arc_summary.ArcSummary.GCOV_ARC_FAKE)
-
-        self.stream = MockStream.concat_int(self.stream, 4)  #  fallthrough arc
-        self.stream = MockStream.concat_int(
-            self.stream, arc_summary.ArcSummary.GCOV_ARC_FALLTHROUGH)
-
-        parser = gcno_parser.GCNOParser(self.stream)
-        parser.ReadArcs(4 * 2 + 1, func)
-
-        self.assertFalse(func.blocks[0].exit_arcs[0].on_tree)
-        self.assertFalse(func.blocks[0].exit_arcs[0].fake)
-        self.assertFalse(func.blocks[0].exit_arcs[0].fallthrough)
-
-        self.assertTrue(func.blocks[0].exit_arcs[1].on_tree)
-        self.assertFalse(func.blocks[0].exit_arcs[1].fake)
-        self.assertFalse(func.blocks[0].exit_arcs[1].fallthrough)
-
-        self.assertFalse(func.blocks[0].exit_arcs[2].on_tree)
-        self.assertTrue(func.blocks[0].exit_arcs[2].fake)
-        self.assertFalse(func.blocks[0].exit_arcs[2].fallthrough)
-
-        self.assertFalse(func.blocks[0].exit_arcs[3].on_tree)
-        self.assertFalse(func.blocks[0].exit_arcs[3].fake)
-        self.assertTrue(func.blocks[0].exit_arcs[3].fallthrough)
-
-    def testReadLines(self):
-        """Asserts that lines are read correctly.
-
-        Blocks must have correct references to the lines contained
-        in the block.
-        """
-        self.stream = MockStream.concat_int(self.stream, 2)  #  block number
-        self.stream = MockStream.concat_int(self.stream, 0)  #  dummy
-        name = "src.c"
-        name_length = int(
-            math.ceil(1.0 * len(name) / MockStream.BYTES_PER_WORD)) + 1
-        self.stream = MockStream.concat_string(self.stream, name)
-        n_arcs = 5
-        for i in range(1, n_arcs + 1):
-            self.stream = MockStream.concat_int(self.stream, i)
-
-        n_blocks = 5
-        func = function_summary.FunctionSummary(0, "func", name, 1)
-        func.blocks = [block_summary.BlockSummary(i, 3 * i)
-                       for i in range(n_blocks)]
-        parser = gcno_parser.GCNOParser(self.stream)
-        parser.ReadLines(n_arcs + name_length + 3, func)
-        self.assertEqual(len(func.blocks[2].lines), 5)
-        self.assertEqual(func.blocks[2].lines, range(1, 6))
-
-    def testSampleFile(self):
-        """Asserts correct parsing of sample GCNO file.
-
-        Verifies the blocks and lines for each function in
-        the file.
-        """
-        dir_path = os.path.dirname(os.path.realpath(__file__))
-        file_path = os.path.join(dir_path, self.GOLDEN_GCNO_PATH)
-        summary = gcno_parser.ParseGcnoFile(file_path)
-        self.assertEqual(len(summary.functions), 2)
-
-        # Check function: testFunctionName
-        func = summary.functions[4]
-        self.assertEqual(func.name, 'testFunctionName')
-        self.assertEqual(func.src_file_name, 'sample.c')
-        self.assertEqual(func.first_line_number, 35)
-        self.assertEqual(len(func.blocks), 5)
-        expected_list = [[], [], [35, 40, 41], [42], []]
-        for index, expected in zip(range(5), expected_list):
-            self.assertEqual(func.blocks[index].lines, expected)
-
-        # Check function: main
-        func = summary.functions[3]
-        self.assertEqual(func.name, 'main')
-        self.assertEqual(func.first_line_number, 5)
-        self.assertEqual(len(func.blocks), 12)
-        self.assertEqual(func.blocks[0].lines, [])
-        expected_list = [[], [], [5, 11, 12, 13], [15], [17], [18], [20],
-                         [23, 24, 25], [26, 25], [], [29], [31]]
-        for index, expected in zip(range(12), expected_list):
-            self.assertEqual(func.blocks[index].lines, expected)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/utils/python/coverage/parser.py b/utils/python/coverage/parser.py
deleted file mode 100644
index fbee873..0000000
--- a/utils/python/coverage/parser.py
+++ /dev/null
@@ -1,116 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-"""Generic parser class for reading GCNO and GCDA files.
-
-Implements read functions for strings, 32-bit integers, and
-64-bit integers.
-"""
-
-import struct
-
-
-class FileFormatError(Exception):
-    """Exception for invalid file format.
-
-    Thrown when an unexpected value type is read from the file stream
-    or when the end of file is reached unexpectedly."""
-
-    pass
-
-
-class GcovStreamParserUtil(object):
-    """Parser object for storing the stream and format information.
-
-    Attributes:
-        stream: File stream object for a GCNO file
-        format: Character denoting the endianness of the file
-        checksum: The checksum (int) of the file
-    """
-
-    def __init__(self, stream, magic):
-        """Inits the parser with the input stream.
-
-        The byte order is set by default to little endian and the summary file
-        is instantiated with an empty GCNOSummary object.
-
-        Args:
-            stream: An input binary file stream to a .gcno file
-            gcno_summary: The summary from a parsed gcno file
-        """
-        self.stream = stream
-        self.format = '<'
-
-        tag = self.ReadInt()
-        self.version = ''.join(
-            struct.unpack(self.format + 'ssss', self.stream.read(4)))
-        self.checksum = self.ReadInt()
-
-        if tag != magic:
-            tag = struct.unpack('>I', struct.pack('<I', tag))[0]
-            if tag == magic:  #  switch endianness
-                self.format = '>'
-            else:
-                raise FileFormatError('Invalid file format.')
-
-    def ReadInt(self):
-        """Reads and returns an integer from the stream.
-
-        Returns:
-          A 4-byte integer from the stream attribute.
-
-        Raises:
-          FileFormatError: Corrupt file.
-        """
-        try:
-            return struct.unpack(self.format + 'I', self.stream.read(4))[0]
-        except (TypeError, ValueError, struct.error) as error:
-            raise FileFormatError('Corrupt file.')
-
-    def ReadInt64(self):
-        """Reads and returns a 64-bit integer from the stream.
-
-        Returns:
-            An 8-byte integer from the stream attribute.
-
-        Raises:
-            FileFormatError: Corrupt file.
-        """
-        lo = self.ReadInt()
-        hi = self.ReadInt()
-        return (hi << 32) | lo
-
-    def ReadString(self):
-        """Reads and returns a string from the stream.
-
-        First reads an integer denoting the number of words to read,
-        then reads and returns the string with trailing padding characters
-        stripped.
-
-        Returns:
-            A string from the stream attribute.
-
-        Raises:
-            FileFormatError: End of file reached.
-        """
-        length = self.ReadInt() << 2
-        if length > 0:
-            try:
-                return ''.join(
-                    struct.unpack(self.format + 's' * length, self.stream.read(
-                        length))).rstrip('\x00')
-            except (TypeError, ValueError, struct.error):
-                raise FileFormatError('Corrupt file.')
-        return str()
diff --git a/utils/python/coverage/parser_test.py b/utils/python/coverage/parser_test.py
deleted file mode 100644
index 0916f9a..0000000
--- a/utils/python/coverage/parser_test.py
+++ /dev/null
@@ -1,216 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2016 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.
-#
-
-import math
-import os
-import struct
-import unittest
-
-from vts.utils.python.coverage import parser
-
-MAGIC = 0x67636e6f
-
-
-class MockStream(object):
-    """MockStream object allows for mocking file reading behavior.
-
-    Allows for adding integers and strings to the file stream in a
-    specified byte format and then reads them as if from a file.
-
-    Attributes:
-        content: the byte list representing a file stream
-        cursor: the index into the content such that everything before it
-                has been read already.
-    """
-    BYTES_PER_WORD = 4
-
-    def __init__(self, magic=MAGIC, format='<'):
-        self.format = format
-        self.magic = magic
-        version = struct.unpack(format + 'I', '*802')[0]
-        self.content = struct.pack(format + 'III', magic, version, 0)
-        self.cursor = 0
-
-    @classmethod
-    def concat_int(cls, stream, integer):
-        """Returns the stream with a binary formatted integer concatenated.
-
-        Args:
-            stream: the stream to which the integer will be concatenated.
-            integer: the integer to be concatenated to the content stream.
-            format: the string format decorator to apply to the integer.
-
-        Returns:
-            The content with the binary-formatted integer concatenated.
-        """
-        new_content = stream.content + struct.pack(stream.format + 'I',
-                                                   integer)
-        s = MockStream(stream.magic, stream.format)
-        s.content = new_content
-        s.cursor = stream.cursor
-        return s
-
-    @classmethod
-    def concat_int64(cls, stream, integer):
-        """Returns the stream with a binary formatted int64 concatenated.
-
-        Args:
-            stream: the stream to which the integer will be concatenated.
-            integer: the 8-byte int to be concatenated to the content stream.
-            format: the string format decorator to apply to the long.
-
-        Returns:
-            The content with the binary-formatted int64 concatenated.
-        """
-        lo = ((1 << 32) - 1) & integer
-        hi = (integer - lo) >> 32
-        new_content = stream.content + struct.pack(stream.format + 'II', lo,
-                                                   hi)
-        s = MockStream(stream.magic, stream.format)
-        s.content = new_content
-        s.cursor = stream.cursor
-        return s
-
-    @classmethod
-    def concat_string(cls, stream, string):
-        """Returns the stream with a binary formatted string concatenated.
-
-        Preceeds the string with an integer representing the number of
-        words in the string. Pads the string so that it is word-aligned.
-
-        Args:
-            stream: the stream to which the string will be concatenated.
-            string: the string to be concatenated to the content stream.
-            format: the string format decorator to apply to the integer.
-
-        Returns:
-            The content with the formatted binary string concatenated.
-        """
-        byte_count = len(string)
-        word_count = int(
-            math.ceil(byte_count * 1.0 / MockStream.BYTES_PER_WORD))
-        padding = '\x00' * (
-            MockStream.BYTES_PER_WORD * word_count - byte_count)
-        new_content = stream.content + struct.pack(
-            stream.format + 'I', word_count) + bytes(string + padding)
-        s = MockStream(stream.magic, stream.format)
-        s.content = new_content
-        s.cursor = stream.cursor
-        return s
-
-    def read(self, n_bytes):
-        """Reads the specified number of bytes from the content stream.
-
-        Args:
-            n_bytes: integer number of bytes to read.
-
-        Returns:
-            The string of length n_bytes beginning at the cursor location
-            in the content stream.
-        """
-        content = self.content[self.cursor:self.cursor + n_bytes]
-        self.cursor += n_bytes
-        return content
-
-
-class ParserTest(unittest.TestCase):
-    """Tests for stream parser of vts.utils.python.coverage.
-
-    Ensures error handling, byte order detection, and correct
-    parsing of integers and strings.
-    """
-
-    def setUp(self):
-        """Creates a stream for each test.
-      """
-        self.stream = MockStream()
-
-    def testLittleEndiannessInitialization(self):
-        """Tests parser init  with little-endian byte order.
-
-        Verifies that the byte-order is correctly detected.
-        """
-        p = parser.GcovStreamParserUtil(self.stream, MAGIC)
-        self.assertEqual(p.format, '<')
-
-    def testBigEndiannessInitialization(self):
-        """Tests parser init with big-endian byte order.
-
-        Verifies that the byte-order is correctly detected.
-        """
-        self.stream = MockStream(format='>')
-        p = parser.GcovStreamParserUtil(self.stream, MAGIC)
-        self.assertEqual(p.format, '>')
-
-    def testReadIntNormal(self):
-        """Asserts that integers are correctly read from the stream.
-
-        Tests the normal case--when the value is actually an integer.
-        """
-        integer = 2016
-        self.stream = MockStream.concat_int(self.stream, integer)
-        p = parser.GcovStreamParserUtil(self.stream, MAGIC)
-        self.assertEqual(p.ReadInt(), integer)
-
-    def testReadIntEof(self):
-        """Asserts that an error is thrown when the EOF is reached.
-        """
-        p = parser.GcovStreamParserUtil(self.stream, MAGIC)
-        self.assertRaises(parser.FileFormatError, p.ReadInt)
-
-    def testReadInt64(self):
-        """Asserts that longs are read correctly.
-        """
-        number = 68719476836
-        self.stream = MockStream.concat_int64(self.stream, number)
-        p = parser.GcovStreamParserUtil(self.stream, MAGIC)
-        self.assertEqual(number, p.ReadInt64())
-
-        self.stream = MockStream(format='>')
-        self.stream = MockStream.concat_int64(self.stream, number)
-        p = parser.GcovStreamParserUtil(self.stream, MAGIC)
-        self.assertEqual(number, p.ReadInt64())
-
-    def testReadStringNormal(self):
-        """Asserts that strings are correctly read from the stream.
-
-        Tests the normal case--when the string is correctly formatted.
-        """
-        test_string = "This is a test."
-        self.stream = MockStream.concat_string(self.stream, test_string)
-        p = parser.GcovStreamParserUtil(self.stream, MAGIC)
-        self.assertEqual(p.ReadString(), test_string)
-
-    def testReadStringError(self):
-        """Asserts that invalid string format raises error.
-
-        Tests when the string length is too short and EOF is reached.
-        """
-        test_string = "This is a test."
-        byte_count = len(test_string)
-        word_count = int(round(byte_count / 4.0))
-        padding = '\x00' * (4 * word_count - byte_count)
-        test_string_padded = test_string + padding
-        content = struct.pack('<I', word_count + 1)  #  will cause EOF error
-        content += bytes(test_string_padded)
-        self.stream.content += content
-        p = parser.GcovStreamParserUtil(self.stream, MAGIC)
-        self.assertRaises(parser.FileFormatError, p.ReadString)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/utils/python/coverage/sancov_parser.py b/utils/python/coverage/sancov_parser.py
deleted file mode 100644
index b74f943..0000000
--- a/utils/python/coverage/sancov_parser.py
+++ /dev/null
@@ -1,105 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-"""Parses the contents of a sancov file generated by LLVM Sanitizer Coverage.
-
-
-    Typical usage example:
-
-    ParseSancovFile(file_name)
-"""
-
-import struct
-import parser
-
-
-MAGIC32 = 0xC0BFFFFFFFFFFF32
-MAGIC64 = 0xC0BFFFFFFFFFFF64
-
-
-class SancovParser(object):
-    """Sancov parser object to represent *.sancov files.
-
-    Attributes:
-        _sancov_file: the stream-like file handle to a sancov file
-        _bitness: the bitness of the offsets (32/64)
-        _entry_type: the type of each offset (32bit->Integer, 64bit->Long)
-    """
-
-    def __init__(self, sancov_file):
-        """Inits the parser with the input stream and default values.
-
-        Args:
-            sancov_file: An input binary file stream to a .sancov file
-        """
-        self._sancov_file = sancov_file
-        self._bitness = -1
-        self._entry_type = None
-        self._size = 0
-
-    def Parse(self):
-        """Runs the parser to generate the unpacked binary offsets in the file.
-
-        Returns:
-            A tuple of offsets into the original binary.
-
-        Raises:
-            parser.FileFormatError: invalid file format or invalid counts.
-        """
-        self.GetBitness()
-        return struct.unpack_from(
-            self._entry_type * (self._size * 8 / self._bitness),
-            self._sancov_file.read(self._size))
-
-    def GetBitness(self):
-        """Parses the magic header to determine the bitness.
-
-        Returns:
-            The sancov file bitness.
-
-        Raises:
-            parser.FileFormatError: invalid file format or invalid counts.
-        """
-        if self._bitness > 0:
-            return self._bitness
-        self._sancov_file.seek(0, 2)
-        self._size = self._sancov_file.tell() - 8
-        self._sancov_file.seek(0, 0)
-        if self._size < 0:
-            raise parser.FileFormatError('Empty file.')
-        magic = struct.unpack('L', self._sancov_file.read(8))[0];
-        if magic == MAGIC64:
-            self._entry_type = 'L'
-            self._bitness = 64
-        elif magic == MAGIC32:
-            self._entry_type = 'I'
-            self._bitness = 32
-        else:
-            raise parser.FileFormatError('Invalid magic.')
-        return self._bitness
-
-def ParseSancovFile(file_name):
-    """Parses the .sancov file specified by the input.
-
-    Args:
-        file_name: A string file path to a .sancov file
-
-    Returns:
-        A tuple of bitness, and the unpacked offsets into the original binary.
-    """
-    with open(file_name, 'rb') as stream:
-        p = SancovParser(stream)
-        offsets = p.Parse()
-        return (p._bitness, offsets)
diff --git a/utils/python/coverage/sancov_parser_test.py b/utils/python/coverage/sancov_parser_test.py
deleted file mode 100644
index 852f2f2..0000000
--- a/utils/python/coverage/sancov_parser_test.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 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.
-#
-
-import io
-import struct
-import unittest
-import sys
-import os
-
-import parser
-import sancov_parser
-
-
-class SancovParserTest(unittest.TestCase):
-    """Tests for sancov_parser in package vts.utils.python.coverage.
-
-    Ensures error handling, bitness detection, and correct
-    parsing of offsets in the file..
-    """
-
-    GOLDEN_SANCOV_PATH = os.path.join(sys.path[0], 'testdata/sample.sancov')
-    GOLDEN_EXPECTED_BITNESS = 64
-    GOLDEN_EXPECTED_OFFSETS = (
-        12115, 12219, 12463, 12527, 17123, 17311, 17507, 17771, 17975, 17987, 18107, 18167,
-        18299, 18503, 18571, 18743, 18755, 18791, 18903, 19127, 19715, 21027, 21123, 21223,
-        21335, 21407, 21455, 21611, 21643, 21683, 23227, 23303, 23343, 23503, 23767, 23779,
-        23791, 23819, 23867, 24615, 24651, 24743, 24775)
-
-    def testInvalidMagic(self):
-        """Asserts that an exception is raised when the magic is invalid.
-        """
-        stream = io.BytesIO(struct.pack('L', 0xC0BFFFFFFFFFFF10))
-        p = sancov_parser.SancovParser(stream)
-        with self.assertRaises(parser.FileFormatError) as context:
-            p.Parse()
-        self.assertTrue('Invalid magic' in str(context.exception))
-
-    def testMagic32(self):
-        """Asserts that values are correctly read in 32-bit sancov files.
-        """
-        stream = io.BytesIO(struct.pack('L', sancov_parser.MAGIC32))
-        stream.seek(8)
-        values = (1, 2, 3)
-        stream.write(struct.pack('III', *values))
-        stream.seek(0)
-        p = sancov_parser.SancovParser(stream)
-        s = p.Parse()
-        self.assertEqual(32, p._bitness)
-        self.assertEqual(values, s)
-
-    def testMagic64(self):
-        """Asserts that values are correctly read in 64-bit sancov files.
-        """
-        stream = io.BytesIO(struct.pack('L', sancov_parser.MAGIC64))
-        stream.seek(8)
-        values = (4, 5, 6)
-        stream.write(struct.pack('LLL', *values))
-        stream.seek(0)
-        p = sancov_parser.SancovParser(stream)
-        s = p.Parse()
-        self.assertEqual(64, p._bitness)
-        self.assertEqual(values, s)
-
-    def testGetBitness32(self):
-        """Asserts that bitness is correctly determined from a 32-bit sancov file.
-        """
-        stream = io.BytesIO(struct.pack('L', sancov_parser.MAGIC32))
-        p = sancov_parser.SancovParser(stream)
-        self.assertEqual(32, p.GetBitness())
-
-    def testGetBitness64(self):
-        """Asserts that bitness is correctly determined from a 64-bit sancov file.
-        """
-        stream = io.BytesIO(struct.pack('L', sancov_parser.MAGIC64))
-        p = sancov_parser.SancovParser(stream)
-        self.assertEqual(64, p.GetBitness())
-
-    def testGolden(self):
-        """Asserts that offsets are correctly parsed from the golden file.
-        """
-        bitness, offsets = sancov_parser.ParseSancovFile(self.GOLDEN_SANCOV_PATH)
-        self.assertEqual(self.GOLDEN_EXPECTED_BITNESS, bitness)
-        self.assertEqual(self.GOLDEN_EXPECTED_OFFSETS, offsets)
-
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/utils/python/coverage/sancov_utils.py b/utils/python/coverage/sancov_utils.py
deleted file mode 100644
index 17b0954..0000000
--- a/utils/python/coverage/sancov_utils.py
+++ /dev/null
@@ -1,346 +0,0 @@
-#
-# Copyright (C) 2017 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.
-import json
-import logging
-import os
-import shutil
-import subprocess
-import tempfile
-import zipfile
-
-from vts.runners.host import keys
-from vts.utils.python.web import feature_utils
-from vts.utils.python.controllers.adb import AdbError
-from vts.utils.python.coverage import sancov_parser
-
-
-class SancovFeature(feature_utils.Feature):
-    """Feature object for sanitizer coverage functionality.
-
-    Attributes:
-        enabled: boolean, True if sancov is enabled, False otherwise
-        web: (optional) WebFeature, object storing web feature util for test run
-    """
-    _DEFAULT_EXCLUDE_PATHS = [
-        'bionic', 'external/libcxx', 'system/core', 'system/libhidl'
-    ]
-    _TOGGLE_PARAM = keys.ConfigKeys.IKEY_ENABLE_SANCOV
-    _REQUIRED_PARAMS = [keys.ConfigKeys.IKEY_ANDROID_DEVICE]
-
-    _PROCESS_INIT_COMMAND = (
-        '\"echo coverage=1 > /data/asan/system/asan.options.{0} && '
-        'echo coverage_dir={1}/{2} >> /data/asan/system/asan.options.{0} && '
-        'rm -rf {1}/{2} &&'
-        'mkdir {1}/{2} && '
-        'killall {0}\"')
-    _FLUSH_COMMAND = '/data/local/tmp/vts_coverage_configure flush {0}'
-    _TARGET_SANCOV_PATH = '/data/misc/trace'
-    _SEARCH_PATHS = [(os.path.join('data', 'asan', 'vendor', 'bin'),
-                      None), (os.path.join('vendor', 'bin'), None),
-                     (os.path.join('data', 'asan', 'vendor', 'lib'),
-                      32), (os.path.join('vendor', 'lib'), 32), (os.path.join(
-                          'data', 'asan', 'vendor',
-                          'lib64'), 64), (os.path.join('vendor', 'lib64'), 64)]
-
-    _BUILD_INFO = 'BUILD_INFO'
-    _REPO_DICT = 'repo-dict'
-    _SYMBOLS_ZIP = 'symbols.zip'
-
-    def __init__(self,
-                 user_params,
-                 web=None,
-                 exclude_paths=_DEFAULT_EXCLUDE_PATHS):
-        """Initializes the sanitizer coverage feature.
-
-        Args:
-            user_params: A dictionary from parameter name (String) to parameter value.
-            web: (optional) WebFeature, object storing web feature util for test run.
-            exclude_paths: (optional) list of strings, paths to exclude for coverage.
-        """
-        self.ParseParameters(
-            self._TOGGLE_PARAM, self._REQUIRED_PARAMS, user_params=user_params)
-        self.web = web
-        self._device_resource_dict = {}
-        self._file_vectors = {}
-        self._exclude_paths = exclude_paths
-        if self.enabled:
-            android_devices = getattr(self,
-                                      keys.ConfigKeys.IKEY_ANDROID_DEVICE)
-            if not isinstance(android_devices, list):
-                logging.warn('Android device information not available')
-                self.enabled = False
-            for device in android_devices:
-                serial = str(device.get(keys.ConfigKeys.IKEY_SERIAL))
-                sancov_resource_path = str(
-                    device.get(keys.ConfigKeys.IKEY_SANCOV_RESOURCES_PATH))
-                if not serial or not sancov_resource_path:
-                    logging.warn('Missing sancov information in device: %s',
-                                 device)
-                    continue
-                self._device_resource_dict[serial] = sancov_resource_path
-        if self.enabled:
-            logging.info('Sancov is enabled.')
-        else:
-            logging.debug('Sancov is disabled.')
-
-    def InitializeDeviceCoverage(self, dut, hals):
-        """Initializes the sanitizer coverage on the device for the provided HAL.
-
-        Args:
-            dut: The device under test.
-            hals: A list of the HAL name and version (string) for which to
-                  measure coverage (e.g. ['android.hardware.light@2.0'])
-        """
-        serial = dut.adb.shell('getprop ro.serialno').strip()
-        if serial not in self._device_resource_dict:
-            logging.error("Invalid device provided: %s", serial)
-            return
-
-        for hal in hals:
-            entries = dut.adb.shell(
-                'lshal -itp 2> /dev/null | grep {0}'.format(hal)).splitlines()
-            pids = set([
-                pid.strip()
-                for pid in map(lambda entry: entry.split()[-1], entries)
-                if pid.isdigit()
-            ])
-
-            if len(pids) == 0:
-                logging.warn('No matching processes IDs found for HAL %s', hal)
-                return
-            processes = dut.adb.shell('ps -p {0} -o comm='.format(
-                ' '.join(pids))).splitlines()
-            process_names = set([
-                name.strip() for name in processes
-                if name.strip() and not name.endswith(' (deleted)')
-            ])
-
-            if len(process_names) == 0:
-                logging.warn('No matching processes names found for HAL %s',
-                             hal)
-                return
-
-            for process_name in process_names:
-                cmd = self._PROCESS_INIT_COMMAND.format(
-                    process_name, self._TARGET_SANCOV_PATH, hal)
-                try:
-                    dut.adb.shell(cmd.format(process_name))
-                except AdbError as e:
-                    logging.error('Command failed: \"%s\"', cmd)
-                    continue
-
-    def FlushDeviceCoverage(self, dut, hals):
-        """Flushes the sanitizer coverage on the device for the provided HAL.
-
-        Args:
-            dut: The device under test.
-            hals: A list of HAL name and version (string) for which to flush
-                  coverage (e.g. ['android.hardware.light@2.0-service'])
-        """
-        serial = dut.adb.shell('getprop ro.serialno').strip()
-        if serial not in self._device_resource_dict:
-            logging.error('Invalid device provided: %s', serial)
-            return
-        for hal in hals:
-            dut.adb.shell(self._FLUSH_COMMAND.format(hal))
-
-    def _InitializeFileVectors(self, serial, binary_path):
-        """Parse the binary and read the debugging information.
-
-        Parse the debugging information in the binary to determine executable lines
-        of code for all of the files included in the binary.
-
-        Args:
-            serial: The serial of the device under test.
-            binary_path: The path to the unstripped binary on the host.
-        """
-        file_vectors = self._file_vectors[serial]
-        args = ['readelf', '--debug-dump=decodedline', binary_path]
-        with tempfile.TemporaryFile('w+b') as tmp:
-            subprocess.call(args, stdout=tmp)
-            tmp.seek(0)
-            file = None
-            for entry in tmp:
-                entry_parts = entry.split()
-                if len(entry_parts) == 0:
-                    continue
-                elif len(entry_parts) < 3 and entry_parts[-1].endswith(':'):
-                    file = entry_parts[-1].rsplit(':')[0]
-                    for path in self._exclude_paths:
-                        if file.startswith(path):
-                            file = None
-                            break
-                    continue
-                elif len(entry_parts) == 3 and file is not None:
-                    line_no_string = entry_parts[1]
-                    try:
-                        line = int(line_no_string)
-                    except ValueError:
-                        continue
-                    if file not in file_vectors:
-                        file_vectors[file] = [-1] * line
-                    if line > len(file_vectors[file]):
-                        file_vectors[file].extend(
-                            [-2] * (line - len(file_vectors[file])))
-                    file_vectors[file][line - 1] = 0
-
-    def _UpdateLineCounts(self, serial, lines):
-        """Update the line counts with the symbolized output lines.
-
-        Increment the line counts using the symbolized line information.
-
-        Args:
-            serial: The serial of the device under test.
-            lines: A list of strings in the format returned by addr2line (e.g. <file>:<line no>).
-        """
-        file_vectors = self._file_vectors[serial]
-        for line in lines:
-            file, line_no_string = line.rsplit(':', 1)
-            if file == '??':  # some lines cannot be symbolized and will report as '??'
-                continue
-            try:
-                line_no = int(line_no_string)
-            except ValueError:
-                continue  # some lines cannot be symbolized and will report as '??'
-            if not file in file_vectors:  # file is excluded
-                continue
-            if line_no > len(file_vectors[file]):
-                file_vectors[file].extend([-1] *
-                                          (line_no - len(file_vectors[file])))
-            if file_vectors[file][line_no - 1] < 0:
-                file_vectors[file][line_no - 1] = 0
-            file_vectors[file][line_no - 1] += 1
-
-    def Upload(self):
-        """Append the coverage information to the web proto report.
-        """
-        if not self.web or not self.web.enabled:
-            return
-
-        for device_serial in self._device_resource_dict:
-            resource_path = self._device_resource_dict[device_serial]
-            rev_map = json.load(
-                open(os.path.join(resource_path,
-                                  self._BUILD_INFO)))[self._REPO_DICT]
-
-            for file in self._file_vectors[device_serial]:
-
-                # Get the git project information
-                # Assumes that the project name and path to the project root are similar
-                revision = None
-                for project_name in rev_map:
-                    # Matches when source file root and project name are the same
-                    if file.startswith(str(project_name)):
-                        git_project_name = str(project_name)
-                        git_project_path = str(project_name)
-                        revision = str(rev_map[project_name])
-                        break
-
-                    parts = os.path.normpath(str(project_name)).split(
-                        os.sep, 1)
-                    # Matches when project name has an additional prefix before the project path root.
-                    if len(parts) > 1 and file.startswith(parts[-1]):
-                        git_project_name = str(project_name)
-                        git_project_path = parts[-1]
-                        revision = str(rev_map[project_name])
-                        break
-
-                if not revision:
-                    logging.info("Could not find git info for %s", file)
-                    continue
-
-                covered_count = sum(
-                    map(lambda count: 1 if count > 0 else 0,
-                        self._file_vectors[device_serial][file]))
-                total_count = sum(
-                    map(lambda count: 1 if count >= 0 else 0,
-                        self._file_vectors[device_serial][file]))
-                self.web.AddCoverageReport(
-                    self._file_vectors[device_serial][file], file,
-                    git_project_name, git_project_path, revision,
-                    covered_count, total_count, True)
-
-    def ProcessDeviceCoverage(self, dut, hals):
-        """Process device coverage.
-
-        Fetch sancov files from the target, parse the sancov files, symbolize the output,
-        and update the line counters.
-
-        Args:
-            dut: The device under test.
-            hals: A list of HAL name and version (string) for which to process
-                  coverage (e.g. ['android.hardware.light@2.0'])
-        """
-        serial = dut.adb.shell('getprop ro.serialno').strip()
-        product = dut.adb.shell('getprop ro.build.product').strip()
-
-        if not serial in self._device_resource_dict:
-            logging.error('Invalid device provided: %s', serial)
-            return
-
-        if serial not in self._file_vectors:
-            self._file_vectors[serial] = {}
-
-        symbols_zip = zipfile.ZipFile(
-            os.path.join(self._device_resource_dict[serial],
-                         self._SYMBOLS_ZIP))
-
-        sancov_files = []
-        for hal in hals:
-            sancov_files.extend(
-                dut.adb.shell('find {0}/{1} -name \"*.sancov\"'.format(
-                    self._TARGET_SANCOV_PATH, hal)).splitlines())
-        temp_dir = tempfile.mkdtemp()
-
-        binary_to_sancov = {}
-        for file in sancov_files:
-            dut.adb.pull(file, temp_dir)
-            binary, pid, _ = os.path.basename(file).rsplit('.', 2)
-            bitness, offsets = sancov_parser.ParseSancovFile(
-                os.path.join(temp_dir, os.path.basename(file)))
-            binary_to_sancov[binary] = (bitness, offsets)
-
-        for hal in hals:
-            dut.adb.shell('rm -rf {0}/{1}'.format(self._TARGET_SANCOV_PATH,
-                                                  hal))
-
-        search_root = os.path.join('out', 'target', 'product', product,
-                                   'symbols')
-        for path, bitness in self._SEARCH_PATHS:
-            for name in [
-                    f for f in symbols_zip.namelist()
-                    if f.startswith(os.path.join(search_root, path))
-            ]:
-                basename = os.path.basename(name)
-                if basename in binary_to_sancov and (
-                        bitness is None
-                        or binary_to_sancov[basename][0] == bitness):
-                    with symbols_zip.open(
-                            name) as source, tempfile.NamedTemporaryFile(
-                                'w+b') as target:
-                        shutil.copyfileobj(source, target)
-                        target.seek(0)
-                        self._InitializeFileVectors(serial, target.name)
-                        addrs = map(lambda addr: '{0:#x}'.format(addr),
-                                    binary_to_sancov[basename][1])
-                        args = ['addr2line', '-pe', target.name]
-                        args.extend(addrs)
-                        with tempfile.TemporaryFile('w+b') as tmp:
-                            subprocess.call(args, stdout=tmp)
-                            tmp.seek(0)
-                            c = tmp.read().split()
-                            self._UpdateLineCounts(serial, c)
-                        del binary_to_sancov[basename]
-        shutil.rmtree(temp_dir)
diff --git a/utils/python/coverage/testdata/sample.c b/utils/python/coverage/testdata/sample.c
deleted file mode 100644
index 39d245a..0000000
--- a/utils/python/coverage/testdata/sample.c
+++ /dev/null
@@ -1,43 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-
-
-int main(argc, argv)
-int argc;
-char **argv;
-
-{
-  int x, y;
-  x = 100;
-  y = 250;
-  testFunctionName(x + y);
-
-  printf("The value of x is %d. \n", x);
-
-  if (x > y) {
-    printf("X is bigger.");
-  } else {
-    printf("Y is bigger.");
-  }
-
-  int z = 0;
-  int i = 0;
-  for (; i < y; i++) {
-    z = -z + 2*i;
-  }
-
-  printf("The value of z is %d.\n", z);
-
-  exit(0);
-
-}
-
-int testFunctionName(a)
-int a;
-
-{
-  int b;
-  b = a << 2;
-  printf("%i times 4 = %i\n", a, b);
-  return b;
-}
\ No newline at end of file
diff --git a/utils/python/coverage/testdata/sample.gcda b/utils/python/coverage/testdata/sample.gcda
deleted file mode 100644
index 144d91d..0000000
--- a/utils/python/coverage/testdata/sample.gcda
+++ /dev/null
Binary files differ
diff --git a/utils/python/coverage/testdata/sample.gcno b/utils/python/coverage/testdata/sample.gcno
deleted file mode 100644
index 2f99907..0000000
--- a/utils/python/coverage/testdata/sample.gcno
+++ /dev/null
Binary files differ
diff --git a/utils/python/coverage/testdata/sample.sancov b/utils/python/coverage/testdata/sample.sancov
deleted file mode 100644
index b65650b..0000000
--- a/utils/python/coverage/testdata/sample.sancov
+++ /dev/null
Binary files differ