diff --git a/tools/deps_guard/rules/ChipsetsdkSP/chipsetsdk_sp_indirect_info.json b/tools/deps_guard/rules/ChipsetsdkSP/chipsetsdk_sp_indirect_info.json new file mode 100755 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tools/deps_guard/rules/ChipsetsdkSP/chipsetsdk_sp_info.json b/tools/deps_guard/rules/ChipsetsdkSP/chipsetsdk_sp_info.json new file mode 100755 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tools/deps_guard/rules/LLndk/llndk_info.json b/tools/deps_guard/rules/LLndk/llndk_info.json new file mode 100755 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tools/deps_guard/rules/Passthrough/passthrough_indirect_info.json b/tools/deps_guard/rules/Passthrough/passthrough_indirect_info.json new file mode 100755 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tools/deps_guard/rules/Passthrough/passthrough_info.json b/tools/deps_guard/rules/Passthrough/passthrough_info.json new file mode 100755 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tools/deps_guard/rules_checker/__init__.py b/tools/deps_guard/rules_checker/__init__.py index 0e59df45af4f2c7062a89c1d905b160dc04a071a..1133b7d18cba8a8b6ff44a7754d9a649644247e4 100755 --- a/tools/deps_guard/rules_checker/__init__.py +++ b/tools/deps_guard/rules_checker/__init__.py @@ -20,6 +20,7 @@ from .napi_rule import NapiRule from .sa_rule import SaRule from .hdi_rule import HdiRule from .chipsetsdk import ChipsetSDKRule +from .base_innerapi_rule import BaseInnerapiRule def check_all_rules(mgr, args): @@ -27,7 +28,8 @@ def check_all_rules(mgr, args): NapiRule, SaRule, HdiRule, - ChipsetSDKRule + ChipsetSDKRule, + BaseInnerapiRule ] passed = True diff --git a/tools/deps_guard/rules_checker/base_innerapi_rule.py b/tools/deps_guard/rules_checker/base_innerapi_rule.py new file mode 100644 index 0000000000000000000000000000000000000000..63c83993a45e603be58bac7c52b91d20abda24c8 --- /dev/null +++ b/tools/deps_guard/rules_checker/base_innerapi_rule.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +#coding=utf-8 + +# +# Copyright (c) 2025 Huawei Device Co., Ltd. +# 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 json + +from .base_rule import BaseRule + + +class BaseInnerapiRule(BaseRule): + RULE_NAME = "BaseInnerApi" + + def __init__(self, mgr, args): + super().__init__(mgr, args) + self.__ignored_tags = ["platformsdk", "sasdk", "platformsdk_indirect", "ndk"] + self.__valid_system_tags = ["llndk", "chipsetsdk", "chipsetsdk_indirect", "chipsetsdk_sp" + "chipsetsdk_sp_indirect"] + self.__ignored_tags + self.__valid_vendor_tags = ["chipsetsdk", "chipsetsdk_indirect", "chipsetsdk_sp", "llndk", "passthrough", + "chipsetsdk_sp_indirect", "passthrough_indirect"] + self.__ignored_tags + + def is_only(self, ignored_tags, mod): + innerapi_tags = mod["innerapi_tags"] + # check whether each innerapi_tag of mod in ignored tags + if innerapi_tags: + for innerapi_tag in innerapi_tags: + if innerapi_tag not in ignored_tags: + return False + # check mod belongs to system module or vendor module + if mod["path"].startswith("system"): + return "system" + else: + return "vendor" + + def check(self): + passed = True + + for mod in self.get_mgr().get_all(): + innerapi_tags = mod["innerapi_tags"] + # mod is system only scene + if self.is_only(self.__ignored_tags, mod) == "system" and \ + all(item in self.__valid_system_tags for item in innerapi_tags): + for dep in mod["deps"]: + callee = dep["callee"] + callee_innerapi_tags = callee["innerapi_tags"] + if self.is_only(self.__ignored_tags, callee) == "system" or \ + all(item in self.__valid_system_tags for item in callee_innerapi_tags): + continue + else: + self.error("system only module %s depends on wrong module as %s in %s" + %(mod["name"], callee["name"], mod["labelPath"])) + passed = False + # mod is vendor only scene + elif self.is_only(self.__ignored_tags, mod) == "vendor" and \ + all(item in self.__valid_vendor_tags for item in innerapi_tags): + for dep in mod["deps"]: + callee = dep["callee"] + callee_innerapi_tags = callee["innerapi_tags"] + if self.is_only(self.__ignored_tags, callee) == "vendor" or \ + all(item in self.__valid_vendor_tags for item in callee_innerapi_tags): + continue + else: + self.error("vendor only module %s depends on wrong module as %s in %s" + %(mod["name"], callee["name"], mod["labelPath"])) + passed = False + return passed \ No newline at end of file diff --git a/tools/deps_guard/rules_checker/base_rule.py b/tools/deps_guard/rules_checker/base_rule.py index 5fbe93f5fcc717be7cd31ce32222e88b06546e0d..7b96d0a8309693892457a322ede5c2510d9cdd87 100755 --- a/tools/deps_guard/rules_checker/base_rule.py +++ b/tools/deps_guard/rules_checker/base_rule.py @@ -68,3 +68,30 @@ class BaseRule(object): def check(self): # Default pass return True + + def check_if_deps_correctly(self, check_modules, valid_mod_tags, valid_dep_tags): + # check if mod and callee have wrong innerapi tags + passed = True + for mod in check_modules: + innerapi_tags = mod["innerapi_tags"] + if innerapi_tags and all(item in valid_mod_tags for item in innerapi_tags): + for dep in mod["deps"]: + callee = dep["callee"] + + dep_innerapi_tags = callee["innerapi_tags"] + if dep_innerapi_tags and all(item in valid_dep_tags for item in dep_innerapi_tags): + continue + elif not dep_innerapi_tags: + continue + + passed = False + wrong_tags = [item for item in dep_innerapi_tags if item not in valid_dep_tags] + self.error("module %s with %s contains wrong dep innerapi_tags [%s] in innerapi_tags [%s]" + %(callee["name"], callee["labelPath"], ",".join(wrong_tags), ",".join(dep_innerapi_tags))) + else: + wrong_tags = [item for item in innerapi_tags if item not in valid_mod_tags] + self.error("module %s with %s contains wrong mod innerapi_tags [%s] in innerapi_tags [%s]" + %(mod["name"], mod["labelPath"], ",".join(wrong_tags), ",".join(innerapi_tags))) + return False + + return passed \ No newline at end of file diff --git a/tools/deps_guard/rules_checker/chipsetsdk.py b/tools/deps_guard/rules_checker/chipsetsdk.py index cc4feef21ffc6158be6c526afa34ed232382301a..e2a1f89b6faa4938c1771527d5fc5c0efb4cadc7 100755 --- a/tools/deps_guard/rules_checker/chipsetsdk.py +++ b/tools/deps_guard/rules_checker/chipsetsdk.py @@ -29,6 +29,9 @@ class ChipsetSDKRule(BaseRule): super().__init__(mgr, args) self.__out_path = mgr.get_product_out_path() self.__white_lists = self.load_chipsetsdk_json("chipsetsdk_info.json") + self.__ignored_tags = ["platformsdk", "sasdk", "platformsdk_indirect", "ndk"] + self.__valid_mod_tags = ["llndk", "chipsetsdk", "chipsetsdk_indirect", "chipsetsdk_sp", + "chipsetsdk_sp_indirect"] + self.__ignored_tags def get_white_lists(self): return self.__white_lists @@ -64,16 +67,31 @@ class ChipsetSDKRule(BaseRule): # Check if all chipset modules depends on chipsetsdk modules only passed = self.__check_depends_on_chipsetsdk() + self.log(f"****check_depends_on_chipsetsdk result:{passed}****") if not passed: return passed # Check if all chipsetsdk module depends on chipsetsdk or chipsetsdk_indirect modules only passed = self.__check_chipsetsdk_indirect() + self.log(f"****check_chipsetsdk_indirect result:{passed}****") if not passed: return passed # Check if all ChipsetSDK modules are correctly tagged by innerapi_tags passed = self.__check_if_tagged_correctly() + self.log(f"****check_if_tagged_correctly result:{passed}****") + if not passed: + return passed + + passed = self.check_if_deps_correctly( + self.__modules_with_chipsetsdk_tag, self.__valid_mod_tags, self.__valid_mod_tags) + self.log(f"****check_if_deps_correctly result:{passed}****") + if not passed: + return passed + + passed = self.check_if_deps_correctly( + self.__modules_with_chipsetsdk_tag, self.__valid_mod_tags, self.__valid_mod_tags) + self.log(f"****check_if_deps_correctly indirect result:{passed}****") if not passed: return passed diff --git a/tools/deps_guard/rules_checker/chipsetsdk_sp.py b/tools/deps_guard/rules_checker/chipsetsdk_sp.py new file mode 100644 index 0000000000000000000000000000000000000000..841800449f7d0d4929c7b8665539bc523f8d2c65 --- /dev/null +++ b/tools/deps_guard/rules_checker/chipsetsdk_sp.py @@ -0,0 +1,265 @@ +#!/usr/bin/env python +#coding=utf-8 + +# +# Copyright (c) 2025 Huawei Device Co., Ltd. +# 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 json + +from .base_rule import BaseRule + + +class ChipsetsdkSPRule(BaseRule): + RULE_NAME = "ChipsetsdkSP" + + def __init__(self, mgr, args): + super().__init__(mgr, args) + self.__out_path = mgr.get_product_out_path() + self.__white_lists = self.load_chipsetsdk_json("chipsetsdk_sp_info.json") + self.__ignored_tags = ["platformsdk", "sasdk", "platformsdk_indirect", "ndk"] + self.__valid_mod_tags = ["llndk", "chipsetsdk_sp", "chipsetsdk_sp_indirect"] + self.__ignored_tags + + def get_white_lists(self): + return self.__white_lists + + def get_out_path(self): + return self.__out_path + + def load_chipsetsdk_json(self, name): + rules_dir = [] + rules_dir.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../rules")) + if self._args and self._args.rules: + self.log("****add more chipsetsdk_sp info in:{}****".format(self._args.rules)) + rules_dir = rules_dir + self._args.rules + + chipsetsdk_rules_path = self.get_out_path().replace("out", "out/products_ext") + if os.path.exists(chipsetsdk_rules_path): + self.log("****add more chipsetsdk_sp info in dir:{}****".format(chipsetsdk_rules_path)) + rules_dir.append(chipsetsdk_rules_path) + else: + self.warn("****add chipsetsdk_sp_rules_path path not exist: {}****".format(chipsetsdk_rules_path)) + res = [] + for d in rules_dir: + rules_file = os.path.join(d, self.__class__.RULE_NAME, name) + if os.path.isfile(rules_file): + res = self.__parser_rules_file(rules_file, res) + else: + self.warn("****rules path not exist: {}****".format(rules_file)) + + return res + + def check(self): + self.__load_chipsetsdk_indirects() + + # Check if all chipset modules depends on chipsetsdk_sp modules only + passed = self.__check_depends_on_chipsetsdk() + self.log(f"****check_depends_on_chipsetsdk result:{passed}****") + if not passed: + return passed + + # Check if all chipsetsdk_sp module depends on chipsetsdk_sp or chipsetsdk_sp_indirect modules only + passed = self.__check_chipsetsdk_sp_indirect() + self.log(f"****check_chipsetsdk_sp_indirect result:{passed}****") + if not passed: + return passed + + # Check if all chipsetsdk_sp modules are correctly tagged by innerapi_tags + passed = self.__check_if_tagged_correctly() + self.log(f"****check_if_tagged_correctly result:{passed}****") + if not passed: + return passed + + passed = self.check_if_deps_correctly( + self.__modules_with_chipsetsdk_sp_tag, self.__valid_mod_tags, self.__valid_mod_tags) + self.log(f"****check_if_deps_correctly result:{passed}****") + if not passed: + return passed + + passed = self.check_if_deps_correctly( + self.__modules_with_chipsetsdk_sp_indirect_tag, self.__valid_mod_tags, self.__valid_mod_tags) + self.log(f"****check_if_deps_correctly indirect result:{passed}****") + if not passed: + return passed + + self.__write_innerkits_header_files() + + return True + + def __parser_rules_file(self, rules_file, res): + try: + self.log("****Parsing rules file in {}****".format(rules_file)) + with open(rules_file, "r") as f: + contents = f.read() + if not contents: + self.log("****rules file {} is null****".format(rules_file)) + return res + json_data = json.loads(contents) + for so in json_data: + so_file_name = so.get("so_file_name") + if so_file_name and so_file_name not in res: + res.append(so_file_name) + except (FileNotFoundError, IOError, UnicodeDecodeError) as file_open_or_decode_err: + self.error(file_open_or_decode_err) + + return res + + def __is_chipsetsdk_sp_tagged(self, mod): + if not "innerapi_tags" in mod: + return False + if "chipsetsdk_sp" in mod["innerapi_tags"]: + return True + return False + + def __is_chipsetsdk_sp_indirect(self, mod): + if not "innerapi_tags" in mod: + return False + if "chipsetsdk_sp_indirect" in mod["innerapi_tags"]: + return True + return False + + def __write_innerkits_header_files(self): + inner_kits_info = os.path.join(self.get_mgr().get_product_out_path(), + "build_configs/parts_info/inner_kits_info.json") + with open(inner_kits_info, "r") as f: + info = json.load(f) + + headers = [] + for sdk in self.__chipsetsdk_sps: + path = sdk["labelPath"][:sdk["labelPath"].find(":")] + target_name = sdk["labelPath"][sdk["labelPath"].find(":") + 1:] + item = {"name": sdk["componentName"] + ":" + target_name, "so_file_name": + sdk["name"], "path": sdk["labelPath"], "headers": []} + if sdk["componentName"] not in info: + headers.append(item) + continue + + for name, innerapi in info[sdk["componentName"]].items(): + if innerapi["label"] != sdk["labelPath"]: + continue + got_headers = True + base = innerapi["header_base"] + for f in innerapi["header_files"]: + item["headers"].append(os.path.join(base, f)) + headers.append(item) + + try: + with os.fdopen(os.open(os.path.join(self.get_mgr().get_product_images_path(), + "chipsetsdk_sp_info.json"), + os.O_WRONLY | os.O_CREAT, 0o644), "w") as f: + json.dump(headers, f, indent=4) + except: + pass + + return headers + + def __check_chipsetsdk_sp_indirect(self): + passed = True + for mod in self.__chipsetsdk_sps: + for dep in mod["deps"]: + callee = dep["callee"] + + # ChipsetSDK SP is OK + if callee["name"] in self.get_white_lists(): + continue + + # chipsetsdk_sp_indirect module is OK + if self.__is_chipsetsdk_sp_indirect(callee) or callee["name"] in self.__indirects: + continue + + # Not correct + passed = False + self.error('ChipsetSPSDK module %s should not depends on non ChipsetSPSDK module \ + %s in %s with "chipsetsdk_indirect"' % (mod["name"], callee["name"], callee["labelPath"])) + + return passed + + def __check_depends_on_chipsetsdk(self): + lists = self.get_white_lists() + + passed = True + + self.__chipsetsdk_sps = [] + self.__modules_with_chipsetsdk_sp_tag = [] + self.__modules_with_chipsetsdk_sp_indirect_tag = [] + + # Check if any napi modules has dependedBy + for mod in self.get_mgr().get_all(): + # Collect all modules with chipsetsdk_sp tag + if self.__is_chipsetsdk_sp_tagged(mod): + self.__modules_with_chipsetsdk_sp_tag.append(mod) + + # Collect all modules with chipsetsdk_sp_indirect tag + if self.__is_chipsetsdk_sp_indirect(mod): + self.__modules_with_chipsetsdk_sp_indirect_tag.append(mod) + + # Check chipset modules only + if mod["path"].startswith("system"): + continue + + # Check chipset modules depends + for dep in mod["deps"]: + callee = dep["callee"] + + # If callee is chipset module, it is OK + if not callee["path"].startswith("system"): + continue + + # Add to list + if callee not in self.__chipsetsdk_sps: + if "hdiType" not in callee or callee["hdiType"] != "hdi_proxy": + self.__chipsetsdk_sps.append(callee) + + # If callee is in ChipsetSDKSP white list module, it is OK + if callee["name"] in lists: + continue + + # If callee is asan library, it is OK + if callee["name"].endswith(".asan.so"): + continue + + # If callee is hdi proxy module, it is OK + if "hdiType" in callee and callee["hdiType"] == "hdi_proxy": + continue + + # Not allowed + passed = False + self.error("chipset module %s depends on non ChipsetSDKSP module %s in %s" + % (mod["name"], callee["name"], mod["labelPath"])) + + return passed + + def __check_if_tagged_correctly(self): + passed = True + for mod in self.__chipsetsdk_sps: + if not self.__is_chipsetsdk_sp_tagged(mod): + self.warn('ChipsetSDK module %s has no innerapi_tags with "chipsetsdk_sp", add it in %s' + % (mod["name"], mod["labelPath"])) + + for mod in self.__modules_with_chipsetsdk_sp_tag: + if mod["name"] not in self.get_white_lists(): + passed = False + self.error('non chipsetsdk_sp module %s with innerapi_tags="chipsetsdk_sp", %s' + % (mod["name"], mod["labelPath"])) + + for mod in self.__modules_with_chipsetsdk_sp_indirect_tag: + if mod["name"] not in self.__indirects and mod["name"] not in self.get_white_lists(): + self.warn('non chipsetsdk_sp_indirect module %s with innerapi_tags="chipsetsdk_sp_indirect", %s' + % (mod["name"], mod["labelPath"])) + + return passed + + def __load_chipsetsdk_indirects(self): + self.__indirects = self.load_chipsetsdk_json("chipsetsdk_sp_indirect.json") diff --git a/tools/deps_guard/rules_checker/llndk.py b/tools/deps_guard/rules_checker/llndk.py new file mode 100644 index 0000000000000000000000000000000000000000..07f4f27f8cf363a8662ddbd142e35f4623172f0e --- /dev/null +++ b/tools/deps_guard/rules_checker/llndk.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +#coding=utf-8 + +# +# Copyright (c) 2025 Huawei Device Co., Ltd. +# 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 json + +from .base_rule import BaseRule + + +class LLndkRule(BaseRule): + RULE_NAME = "LLndk" + + def __init__(self, mgr, args): + super().__init__(mgr, args) + self.__out_path = mgr.get_product_out_path() + self.__white_lists = self.load_llndk_json("llndk_info.json") + self.__ignored_tags = ["platformsdk", "sasdk", "platformsdk_indirect", "ndk"] + self.__valid_mod_tags = ["llndk"] + self.__ignored_tags + + def get_white_lists(self): + return self.__white_lists + + def get_out_path(self): + return self.__out_path + + def load_llndk_json(self, name): + rules_dir = [] + rules_dir.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../rules")) + if self._args and self._args.rules: + self.log("****add more llndk info in:{}****".format(self._args.rules)) + rules_dir = rules_dir + self._args.rules + + llndk_rules_path = self.get_out_path().replace("out", "out/products_ext") + if os.path.exists(llndk_rules_path): + self.log("****add more llndk info in dir:{}****".format(llndk_rules_path)) + rules_dir.append(llndk_rules_path) + else: + self.warn("****add llndk_rules_path path not exist: {}****".format(llndk_rules_path)) + res = [] + for d in rules_dir: + rules_file = os.path.join(d, self.__class__.RULE_NAME, name) + if os.path.isfile(rules_file): + res = self.__parser_rules_file(rules_file, res) + else: + self.warn("****rules path not exist: {}****".format(rules_file)) + + return res + + def check(self): + self.__modules_with_llndk_tag = [] + + for mod in self.get_mgr().get_all(): + if self.__is_llndk_tagged(mod): + self.__modules_with_llndk_tag.append(mod) + + # Check if all llndk modules are correctly tagged by innerapi_tags + passed = self.__check_if_tagged_correctly() + self.log(f"****check_if_tagged_correctly result:{passed}****") + if not passed: + return passed + + passed = self.check_if_deps_correctly( + self.__modules_with_llndk_tag, self.__valid_mod_tags, self.__valid_mod_tags) + self.log(f"****check_if_deps_correctly result:{passed}****") + if not passed: + return passed + + return True + + def __parser_rules_file(self, rules_file, res): + try: + self.log("****Parsing rules file in {}****".format(rules_file)) + with open(rules_file, "r") as f: + contents = f.read() + if not contents: + self.log("****rules file {} is null****".format(rules_file)) + return res + json_data = json.loads(contents) + for so in json_data: + so_file_name = so.get("so_file_name") + if so_file_name and so_file_name not in res: + res.append(so_file_name) + except (FileNotFoundError, IOError, UnicodeDecodeError) as file_open_or_decode_err: + self.error(file_open_or_decode_err) + + return res + + def __is_llndk_tagged(self, mod): + if not "innerapi_tags" in mod: + return False + if "llndk" in mod["innerapi_tags"]: + return True + return False + + def __check_if_tagged_correctly(self): + passed = True + + for mod in self.__modules_with_chipsetsdk_sp_tag: + if mod["name"] not in self.get_white_lists(): + passed = False + self.error('non chipsetsdk_sp module %s with innerapi_tags="chipsetsdk_sp", %s' + % (mod["name"], mod["labelPath"])) + + return passed diff --git a/tools/deps_guard/rules_checker/passthrough.py b/tools/deps_guard/rules_checker/passthrough.py new file mode 100644 index 0000000000000000000000000000000000000000..66b030b09b8c18600e9ce81190c34575907f0df5 --- /dev/null +++ b/tools/deps_guard/rules_checker/passthrough.py @@ -0,0 +1,265 @@ +#!/usr/bin/env python +#coding=utf-8 + +# +# Copyright (c) 2025 Huawei Device Co., Ltd. +# 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 json + +from .base_rule import BaseRule + + +class PassthroughRule(BaseRule): + RULE_NAME = "Passthrough" + + def __init__(self, mgr, args): + super().__init__(mgr, args) + self.__out_path = mgr.get_product_out_path() + self.__white_lists = self.load_passthrough_json("passthrough_info.json") + self.__ignored_tags = ["platformsdk", "sasdk", "platformsdk_indirect", "ndk"] + self.__valid_mod_tags = ["llndk", "chipsetsdk_sp", "passthrough", "passthrough_indirect"] + self.__ignored_tags + + def get_white_lists(self): + return self.__white_lists + + def get_out_path(self): + return self.__out_path + + def load_passthrough_json(self, name): + rules_dir = [] + rules_dir.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../rules")) + if self._args and self._args.rules: + self.log("****add more ChipsetSDK info in:{}****".format(self._args.rules)) + rules_dir = rules_dir + self._args.rules + + chipsetsdk_rules_path = self.get_out_path().replace("out", "out/products_ext") + if os.path.exists(chipsetsdk_rules_path): + self.log("****add more ChipsetSDK info in dir:{}****".format(chipsetsdk_rules_path)) + rules_dir.append(chipsetsdk_rules_path) + else: + self.warn("****add chipsetsdk_rules_path path not exist: {}****".format(chipsetsdk_rules_path)) + res = [] + for d in rules_dir: + rules_file = os.path.join(d, self.__class__.RULE_NAME, name) + if os.path.isfile(rules_file): + res = self.__parser_rules_file(rules_file, res) + else: + self.warn("****rules path not exist: {}****".format(rules_file)) + + return res + + def check(self): + self.__load_passthrough_indirects() + + # Check if all chipset modules depends on chipsetsdk modules only + passed = self.__check_depends_on_passthrough() + self.log(f"****check_depends_on_chipsetsdk result:{passed}****") + if not passed: + return passed + + # Check if all chipsetsdk module depends on chipsetsdk or chipsetsdk_indirect modules only + passed = self.__check_passthrough_indirect() + self.log(f"****check_chipsetsdk_indirect result:{passed}****") + if not passed: + return passed + + # Check if all ChipsetSDK modules are correctly tagged by innerapi_tags + passed = self.__check_if_passthrough_tagged_correctly() + self.log(f"****check_if_tagged_correctly result:{passed}****") + if not passed: + return passed + + passed = self.check_if_deps_correctly( + self.__modules_with_passthrough_tag, self.__valid_mod_tags, self.__valid_mod_tags) + self.log(f"****check_if_deps_correctly result:{passed}****") + if not passed: + return passed + + passed = self.check_if_deps_correctly( + self.__modules_with_passthrough_tag, self.__valid_mod_tags, self.__valid_mod_tags) + self.log(f"****check_if_deps_correctly indirect result:{passed}****") + if not passed: + return passed + + self.__write_innerkits_header_files() + + return True + + def __parser_rules_file(self, rules_file, res): + try: + self.log("****Parsing rules file in {}****".format(rules_file)) + with open(rules_file, "r") as f: + contents = f.read() + if not contents: + self.log("****rules file {} is null****".format(rules_file)) + return res + json_data = json.loads(contents) + for so in json_data: + so_file_name = so.get("so_file_name") + if so_file_name and so_file_name not in res: + res.append(so_file_name) + except (FileNotFoundError, IOError, UnicodeDecodeError) as file_open_or_decode_err: + self.error(file_open_or_decode_err) + + return res + + def __is_passthrough_tagged(self, mod): + if not "innerapi_tags" in mod: + return False + if "passthrough" in mod["innerapi_tags"]: + return True + return False + + def __is_passthrough_indirect(self, mod): + if not "innerapi_tags" in mod: + return False + if "passthrough_indirect" in mod["innerapi_tags"]: + return True + return False + + def __write_innerkits_header_files(self): + inner_kits_info = os.path.join(self.get_mgr().get_product_out_path(), + "build_configs/parts_info/inner_kits_info.json") + with open(inner_kits_info, "r") as f: + info = json.load(f) + + headers = [] + for sdk in self.__passthroughs: + path = sdk["labelPath"][:sdk["labelPath"].find(":")] + target_name = sdk["labelPath"][sdk["labelPath"].find(":") + 1:] + item = {"name": sdk["componentName"] + ":" + target_name, "so_file_name": + sdk["name"], "path": sdk["labelPath"], "headers": []} + if sdk["componentName"] not in info: + headers.append(item) + continue + + for name, innerapi in info[sdk["componentName"]].items(): + if innerapi["label"] != sdk["labelPath"]: + continue + got_headers = True + base = innerapi["header_base"] + for f in innerapi["header_files"]: + item["headers"].append(os.path.join(base, f)) + headers.append(item) + + try: + with os.fdopen(os.open(os.path.join(self.get_mgr().get_product_images_path(), + "passthrough_info.json"), + os.O_WRONLY | os.O_CREAT, 0o644), "w") as f: + json.dump(headers, f, indent=4) + except: + pass + + return headers + + def __check_passthrough_indirect(self): + passed = True + for mod in self.__passthroughs: + for dep in mod["deps"]: + callee = dep["callee"] + + # Passthrough is OK + if callee["name"] in self.get_white_lists(): + continue + + # Passthrough_indirect module is OK + if self.__is_passthrough_indirect(callee) or callee["name"] in self.__indirects: + continue + + # Not correct + passed = False + self.error('Passthrough module %s should not depends on non Passthrough module \ + %s in %s with "chipsetsdk_indirect"' % (mod["name"], callee["name"], callee["labelPath"])) + + return passed + + def __check_depends_on_passthrough(self): + lists = self.get_white_lists() + + passed = True + + self.__passthroughs = [] + self.__modules_with_passthrough_tag = [] + self.__modules_with_passthrough_indirect_tag = [] + + # Check if any napi modules has dependedBy + for mod in self.get_mgr().get_all(): + # Collect all modules with passthrough tag + if self.__is_passthrough_tagged(mod): + self.__modules_with_passthrough_tag.append(mod) + + # Collect all modules with passthrough_indirect tag + if self.__is_passthrough_indirect(mod): + self.__modules_with_passthrough_indirect_tag.append(mod) + + # Check chipset modules only + if mod["path"].startswith("system"): + continue + + # Check chipset modules depends + for dep in mod["deps"]: + callee = dep["callee"] + + # If callee is chipset module, it is OK + if not callee["path"].startswith("system"): + continue + + # Add to list + if callee not in self.__passthroughs: + if "hdiType" not in callee or callee["hdiType"] != "hdi_proxy": + self.__passthroughs.append(callee) + + # If callee is in passthroughwhite list module, it is OK + if callee["name"] in lists: + continue + + # If callee is asan library, it is OK + if callee["name"].endswith(".asan.so"): + continue + + # If callee is hdi proxy module, it is OK + if "hdiType" in callee and callee["hdiType"] == "hdi_proxy": + continue + + # Not allowed + passed = False + self.error("chipset module %s depends on non Chipset SDK module %s in %s" + % (mod["name"], callee["name"], mod["labelPath"])) + + return passed + + def __check_if_passthrough_tagged_correctly(self): + passed = True + for mod in self.__passthroughs: + if not self.__is_passthrough_tagged(mod): + self.warn('passthrough module %s has no innerapi_tags with "passthrough", add it in %s' + % (mod["name"], mod["labelPath"])) + + for mod in self.__modules_with_passthrough_tag: + if mod["name"] not in self.get_white_lists(): + passed = False + self.error('non passthrough %s with innerapi_tags="passthrough", %s' + % (mod["name"], mod["labelPath"])) + + for mod in self.__modules_with_passthrough_indirect_tag: + if mod["name"] not in self.__indirects and mod["name"] not in self.get_white_lists(): + self.warn('non passthrough_indirect module %s with innerapi_tags="passthrough_indirect", %s' + % (mod["name"], mod["labelPath"])) + + return passed + + def __load_passthrough_indirects(self): + self.__indirects = self.load_passthrough_json("passthrough_indirect.json")