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 def _load_module_info_file(self, module_file): 38 """Loads the module file. 39 40 Args: 41 module_file: String of path to file to load up. Used for testing. 42 43 Returns: 44 Tuple of module_info_target and a json object. 45 """ 46 # If module_file is specified, we're testing so we don't care if 47 # module_info_target stays None. 48 module_info_target = None 49 file_path = module_file 50 51 if not file_path: 52 module_info_target, file_path = self._discover_mod_file_and_target( 53 self.force_build) 54 self.mod_info_file_path = Path(file_path) 55 56 logging.debug('Loading %s as module-info.', file_path) 57 with open(file_path, 'r', encoding='utf8') as json_file: 58 mod_info = json.load(json_file) 59 60 return module_info_target, mod_info 61 62 @staticmethod 63 def _discover_mod_file_and_target(force_build): 64 """Find the module file. 65 66 If force_build is True, we'll remove module_bp_java_deps.json first and 67 let module_info_util.generate_merged_module_info regenerate it again. 68 69 Args: 70 force_build: Boolean to indicate if we should rebuild the 71 module_info file regardless if it's created or not. 72 73 Returns: 74 Tuple of the relative and absolute paths of the merged module info 75 file. 76 """ 77 module_file_path = common_util.get_blueprint_json_path( 78 constant.BLUEPRINT_JAVA_JSONFILE_NAME) 79 if force_build and os.path.isfile(module_file_path): 80 os.remove(module_file_path) 81 merged_file_path = os.path.join(common_util.get_soong_out_path(), 82 constant.MERGED_MODULE_INFO) 83 if not os.path.isfile(merged_file_path): 84 logging.debug( 85 'Generating %s - this is required for the initial runs.', 86 merged_file_path) 87 data = module_info_util.generate_merged_module_info() 88 common_util.dump_json_dict(merged_file_path, data) 89 merged_file_rel_path = os.path.relpath( 90 merged_file_path, common_util.get_android_root_dir()) 91 return merged_file_rel_path, merged_file_path 92 93 @staticmethod 94 def is_target_module(mod_info): 95 """Determine if the module is a target module. 96 97 Determine if a module's class is in TARGET_CLASSES. 98 99 Args: 100 mod_info: A module's module-info dictionary to be checked. 101 102 Returns: 103 A boolean, true if it is a target module, otherwise false. 104 """ 105 if mod_info: 106 return any( 107 x in mod_info.get(constants.MODULE_CLASS, []) 108 for x in constant.TARGET_CLASSES) 109 return False 110 111 @staticmethod 112 def is_project_path_relative_module(mod_info, rel_path): 113 """Determine if the given project path is relative to the module. 114 115 The rules: 116 1. If constant.KEY_PATH not in mod_info, we can't tell if it's a 117 module return False. 118 2. If rel_path is empty, it's under Android root, return True. 119 3. If module's path equals or starts with rel_path return True, 120 otherwise return False. 121 122 Args: 123 mod_info: the module-info dictionary of the checked module. 124 rel_path: project's relative path 125 126 Returns: 127 True if it's the given project path is relative to the module, 128 otherwise False. 129 """ 130 if (constant.KEY_PATH not in mod_info 131 or not mod_info[constant.KEY_PATH]): 132 return False 133 path = mod_info[constant.KEY_PATH][0] 134 if rel_path == '': 135 return True 136 if (constant.KEY_CLASS in mod_info 137 and common_util.is_source_under_relative_path(path, rel_path)): 138 return True 139 return False 140