#!/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 logging
import os
import re
import shutil
import tempfile

from vts.runners.host import asserts
from vts.runners.host import base_test
from vts.runners.host import test_runner
from vts.runners.host import utils
from vts.utils.python.controllers import android_device
from vts.utils.python.file import target_file_utils
from vts.utils.python.library import elf_parser
from vts.utils.python.os import path_utils


class VtsVndkDependencyTest(base_test.BaseTestClass):
    """A test case to verify vendor library dependency.

    Attributes:
        _dut: The AndroidDevice under test.
        _shell: The ShellMirrorObject to execute commands
        _temp_dir: The temporary directory to which the vendor partition is
                   copied.
        _LOW_LEVEL_NDK: List of strings. The names of low-level NDK libraries in
                        /system/lib[64].
        _SAME_PROCESS_HAL: List of patterns. The names of same-process HAL
                           libraries expected to be in /vendor/lib[64].
        _SAME_PROCESS_NDK: List if strings. The names of same-process NDK
                           libraries in /system/lib[64].
    """
    _TARGET_VENDOR_DIR = "/vendor"
    _TARGET_VNDK_SP_DIR_32 = "/system/lib/vndk-sp"
    _TARGET_VNDK_SP_DIR_64 = "/system/lib64/vndk-sp"

    # copied from development/vndk/tools/definition-tool/vndk_definition_tool.py
    _LOW_LEVEL_NDK = [
        "libandroid_net.so", "libc.so", "libdl.so", "liblog.so", "libm.so",
        "libstdc++.so", "libvndksupport.so", "libz.so"
    ]
    _SAME_PROCESS_HAL = [
        re.compile(p)
        for p in [
            "android\\.hardware\\.graphics\\.mapper@\\d+\\.\\d+-impl\\.so$",
            "gralloc\\..*\\.so$", "libEGL_.*\\.so$", "libGLES_.*\\.so$",
            "libGLESv1_CM_.*\\.so$", "libGLESv2_.*\\.so$",
            "libGLESv3_.*\\.so$", "libPVRRS\\.so$", "libRSDriver.*\\.so$",
            "vulkan.*\\.so$"
        ]
    ]
    _SAME_PROCESS_NDK = [
        "libEGL.so", "libGLESv1_CM.so", "libGLESv2.so", "libGLESv3.so",
        "libnativewindow.so", "libsync.so", "libvulkan.so"
    ]
    _SP_HAL_LINK_PATHS_32 = [
        "/vendor/lib/egl", "/vendor/lib/hw", "/vendor/lib"
    ]
    _SP_HAL_LINK_PATHS_64 = [
        "/vendor/lib64/egl", "/vendor/lib64/hw", "/vendor/lib64"
    ]

    class ElfObject(object):
        """Contains dependencies of an ELF file on target device.

        Attributes:
            target_path: String. The path to the ELF file on target.
            name: String. File name of the ELF.
            target_dir: String. The directory containing the ELF file on target.
            bitness: Integer. Bitness of the ELF.
            deps: List of strings. The names of the depended libraries.
        """

        def __init__(self, target_path, bitness, deps):
            self.target_path = target_path
            self.name = path_utils.TargetBaseName(target_path)
            self.target_dir = path_utils.TargetDirName(target_path)
            self.bitness = bitness
            self.deps = deps

    def setUpClass(self):
        """Initializes device and temporary directory."""
        self._dut = self.registerController(android_device)[0]
        self._dut.shell.InvokeTerminal("one")
        self._shell = self._dut.shell.one
        self._temp_dir = tempfile.mkdtemp()
        logging.info("adb pull %s %s", self._TARGET_VENDOR_DIR, self._temp_dir)
        pull_output = self._dut.adb.pull(self._TARGET_VENDOR_DIR,
                                         self._temp_dir)
        logging.debug(pull_output)

    def tearDownClass(self):
        """Deletes the temporary directory."""
        logging.info("Delete %s", self._temp_dir)
        shutil.rmtree(self._temp_dir)

    def _loadElfObjects(self, host_dir, target_dir, elf_error_handler):
        """Scans a host directory recursively and loads all ELF files in it.

        Args:
            host_dir: The host directory to scan.
            target_dir: The path from which host_dir is copied.
            elf_error_handler: A function that takes 2 arguments
                               (target_path, exception). It is called when
                               the parser fails to read an ELF file.

        Returns:
            List of ElfObject.
        """
        objs = []
        for root_dir, file_name in utils.iterate_files(host_dir):
            full_path = os.path.join(root_dir, file_name)
            rel_path = os.path.relpath(full_path, host_dir)
            target_path = path_utils.JoinTargetPath(
                target_dir, *rel_path.split(os.path.sep))
            try:
                elf = elf_parser.ElfParser(full_path)
            except elf_parser.ElfError:
                logging.debug("%s is not an ELF file", target_path)
                continue
            try:
                deps = elf.ListDependencies()
            except elf_parser.ElfError as e:
                elf_error_handler(target_path, e)
                continue
            finally:
                elf.Close()

            logging.info("%s depends on: %s", target_path, ", ".join(deps))
            objs.append(self.ElfObject(target_path, elf.bitness, deps))
        return objs

    def _isAllowedSpHalDependency(self, lib_name, vndk_sp_names,
                                  linkable_libs):
        """Checks whether a same-process HAL library dependency is allowed.

        A same-process HAL library is allowed to depend on
        - Low-level NDK
        - Same-process NDK
        - vndk-sp
        - Other libraries in vendor/lib[64]

        Args:
            lib_name: String. The name of the depended library.
            vndk_sp_names: Set of strings. The names of the libraries in
                           vndk-sp directory.
            linkable_libs: Dictionary. The keys are the names of the libraries
                           which can be linked to same-process HAL.

        Returns:
            A boolean representing whether the dependency is allowed.
        """
        if (lib_name in self._LOW_LEVEL_NDK or
                lib_name in self._SAME_PROCESS_NDK or
                lib_name in vndk_sp_names or lib_name in linkable_libs):
            return True
        return False

    def _getTargetVndkSpDir(self, bitness):
        """Returns 32/64-bit vndk-sp directory path on target device."""
        return getattr(self, "_TARGET_VNDK_SP_DIR_" + str(bitness))

    def _getSpHalLinkPaths(self, bitness):
        """Returns 32/64-bit same-process HAL link paths"""
        return getattr(self, "_SP_HAL_LINK_PATHS_" + str(bitness))

    def _isInSpHalLinkPaths(self, lib):
        """Checks whether a library can be linked to same-process HAL.

        Args:
            lib: ElfObject. The library to check.

        Returns:
            True if can be linked to same-process HAL; False otherwise.
        """
        return lib.target_dir in self._getSpHalLinkPaths(lib.bitness)

    def _spHalLinkOrder(self, lib):
        """Returns the key for sorting libraries in linker search order.

        Args:
            lib: ElfObject.

        Returns:
            An integer representing linker search order.
        """
        link_paths = self._getSpHalLinkPaths(lib.bitness)
        for order in range(len(link_paths)):
            if lib.target_dir == link_paths[order]:
                return order
        order = len(link_paths)
        if lib.name in self._LOW_LEVEL_NDK:
            return order
        order += 1
        if lib.name in self._SAME_PROCESS_NDK:
            return order
        order += 1
        return order

    def _dfsDependencies(self, lib, searched, searchable):
        """Depth-first-search for library dependencies.

        Args:
            lib: ElfObject. The library to search dependencies.
            searched: The set of searched libraries.
            searchable: The dictionary that maps file names to libraries.
        """
        if lib in searched:
            return
        searched.add(lib)
        for dep_name in lib.deps:
            if dep_name in searchable:
                self._dfsDependencies(searchable[dep_name], searched,
                                      searchable)

    def _testSpHalDependency(self, bitness, objs):
        """Scans same-process HAL dependency on vendor partition.

        Returns:
            List of tuples (path, dependency_names). The library with
            disallowed dependencies and list of the dependencies.
        """
        vndk_sp_dir = self._getTargetVndkSpDir(bitness)
        vndk_sp_paths = target_file_utils.FindFiles(self._shell, vndk_sp_dir,
                                                    "*.so")
        vndk_sp_names = set(
            path_utils.TargetBaseName(x) for x in vndk_sp_paths)
        logging.info("%s libraries: %s" % (vndk_sp_dir,
                                           ", ".join(vndk_sp_names)))
        # map file names to libraries which can be linked to same-process HAL
        linkable_libs = dict()
        for obj in [
                x for x in objs
                if x.bitness == bitness and self._isInSpHalLinkPaths(x)
        ]:
            if obj.name not in linkable_libs:
                linkable_libs[obj.name] = obj
            else:
                linkable_libs[obj.name] = min(
                    linkable_libs[obj.name], obj, key=self._spHalLinkOrder)
        # find same-process HAL and dependencies
        sp_hal_libs = set()
        for file_name, obj in linkable_libs.iteritems():
            if any([x.match(file_name) for x in self._SAME_PROCESS_HAL]):
                self._dfsDependencies(obj, sp_hal_libs, linkable_libs)
        logging.info("%d-bit SP HAL libraries: %s" %
                     (bitness, ", ".join([x.name for x in sp_hal_libs])))
        # check disallowed dependencies
        dep_errors = []
        for obj in sp_hal_libs:
            disallowed_libs = [
                x for x in obj.deps
                if not self._isAllowedSpHalDependency(x, vndk_sp_names,
                                                      linkable_libs)
            ]
            if disallowed_libs:
                dep_errors.append((obj.target_path, disallowed_libs))
        return dep_errors

    def testElfDependency(self):
        """Scans library/executable dependency on vendor partition."""
        read_errors = []
        objs = self._loadElfObjects(
            self._temp_dir,
            path_utils.TargetDirName(self._TARGET_VENDOR_DIR),
            lambda p, e: read_errors.append((p, str(e))))

        dep_errors = self._testSpHalDependency(32, objs)
        if self._dut.is64Bit:
            dep_errors.extend(self._testSpHalDependency(64, objs))
        # TODO(hsinyichen): check other vendor libraries

        if read_errors:
            logging.error("%d read errors:", len(read_errors))
            for x in read_errors:
                logging.error("%s: %s", x[0], x[1])
        if dep_errors:
            logging.error("%d disallowed dependencies:", len(dep_errors))
            for x in dep_errors:
                logging.error("%s: %s", x[0], ", ".join(x[1]))
        error_count = len(read_errors) + len(dep_errors)
        asserts.assertEqual(error_count, 0,
                            "Total number of errors: " + str(error_count))


if __name__ == "__main__":
    test_runner.main()
