• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright 2019, The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17"""Module Info class used to hold cached merged_module_info.json."""
18
19import json
20import logging
21import os
22
23from pathlib import Path
24
25from atest import constants
26from atest import module_info
27
28from aidegen import constant
29from aidegen.lib import common_util
30from aidegen.lib import module_info_util
31from aidegen.lib.singleton import Singleton
32
33
34class AidegenModuleInfo(module_info.ModuleInfo, metaclass=Singleton):
35    """Class that offers fast/easy lookup for Module related details."""
36
37
38    def _load_module_info_file(self, module_file):
39        """Loads the module file.
40
41        Args:
42            module_file: String of path to file to load up. Used for testing.
43
44        Returns:
45            Tuple of module_info_target and a json object.
46        """
47        # If module_file is specified, we're testing so we don't care if
48        # module_info_target stays None.
49        module_info_target = None
50        file_path = module_file
51
52        if not file_path:
53            module_info_target, file_path = self._discover_mod_file_and_target(
54                self.force_build)
55            self.mod_info_file_path = Path(file_path)
56
57        logging.debug('Loading %s as module-info.', file_path)
58        with open(file_path, encoding='utf8') as json_file:
59            mod_info = json.load(json_file)
60
61        return module_info_target, mod_info
62
63    @staticmethod
64    def _discover_mod_file_and_target(force_build):
65        """Find the module file.
66
67        If force_build is True, we'll remove module_bp_java_deps.json first and
68        let module_info_util.generate_merged_module_info regenerate it again.
69
70        Args:
71            force_build: Boolean to indicate if we should rebuild the
72                         module_info file regardless if it's created or not.
73
74        Returns:
75            Tuple of the relative and absolute paths of the merged module info
76            file.
77        """
78        module_file_path = common_util.get_blueprint_json_path(
79            constant.BLUEPRINT_JAVA_JSONFILE_NAME)
80        if force_build and os.path.isfile(module_file_path):
81            os.remove(module_file_path)
82        merged_file_path = os.path.join(common_util.get_soong_out_path(),
83                                        constant.MERGED_MODULE_INFO)
84        if not os.path.isfile(merged_file_path):
85            logging.debug(
86                'Generating %s - this is required for the initial runs.',
87                merged_file_path)
88        data = module_info_util.generate_merged_module_info()
89        common_util.dump_json_dict(merged_file_path, data)
90        merged_file_rel_path = os.path.relpath(
91            merged_file_path, common_util.get_android_root_dir())
92        return merged_file_rel_path, merged_file_path
93
94    @staticmethod
95    def is_target_module(mod_info):
96        """Determine if the module is a target module.
97
98        Determine if a module's class is in TARGET_CLASSES.
99
100        Args:
101            mod_info: A module's module-info dictionary to be checked.
102
103        Returns:
104            A boolean, true if it is a target module, otherwise false.
105        """
106        if mod_info:
107            return any(
108                x in mod_info.get(constants.MODULE_CLASS, [])
109                for x in constant.TARGET_CLASSES)
110        return False
111
112    @staticmethod
113    def is_project_path_relative_module(mod_info, rel_path):
114        """Determine if the given project path is relative to the module.
115
116        The rules:
117           1. If constant.KEY_PATH not in mod_info, we can't tell if it's a
118              module return False.
119           2. If rel_path is empty, it's under Android root, return True.
120           3. If module's path equals or starts with rel_path return True,
121              otherwise return False.
122
123        Args:
124            mod_info: the module-info dictionary of the checked module.
125            rel_path: project's relative path
126
127        Returns:
128            True if it's the given project path is relative to the module,
129            otherwise False.
130        """
131        if (constant.KEY_PATH not in mod_info
132                or not mod_info[constant.KEY_PATH]):
133            return False
134        path = mod_info[constant.KEY_PATH][0]
135        if rel_path == '':
136            return True
137        if (constant.KEY_CLASS in mod_info
138                and common_util.is_source_under_relative_path(path, rel_path)):
139            return True
140        return False
141