1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4# 5# Copyright (c) 2020 Huawei Device Co., Ltd. 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17 18import os 19from collections import defaultdict 20 21from hb_internal.common.utils import read_json_file 22from hb_internal.common.utils import OHOSException 23from hb_internal.common.config import Config 24from hb_internal.cts.menuconfig import Menuconfig 25from hb_internal.cts.common import Separator 26from hb_internal.preloader.parse_vendor_product_config import get_vendor_parts_list 27 28class Product(): 29 @staticmethod 30 def get_products(): 31 config = Config() 32 # ext products configuration 33 _ext_scan_path = os.path.join(config.root_path, 34 'out/products_ext/vendor') 35 if os.path.exists(_ext_scan_path): 36 for company in os.listdir(_ext_scan_path): 37 company_path = os.path.join(_ext_scan_path, company) 38 if not os.path.isdir(company_path): 39 continue 40 41 for product in os.listdir(company_path): 42 p_config_path = os.path.join(company_path, product) 43 config_path = os.path.join(p_config_path, 'config.json') 44 45 if os.path.isfile(config_path): 46 info = read_json_file(config_path) 47 product_name = info.get('product_name') 48 if info.get('product_path'): 49 product_path = os.path.join( 50 config.root_path, info.get('product_path')) 51 else: 52 product_path = p_config_path 53 if product_name is not None: 54 yield { 55 'company': company, 56 "name": product_name, 57 'product_config_path': p_config_path, 58 'product_path': product_path, 59 'version': info.get('version', '3.0'), 60 'os_level': info.get('type', "mini"), 61 'build_out_path': info.get('build_out_path'), 62 'subsystem_config_json': 63 info.get('subsystem_config_json'), 64 'config': config_path, 65 'component_type': info.get('component_type', '') 66 } 67 for company in os.listdir(config.vendor_path): 68 company_path = os.path.join(config.vendor_path, company) 69 if not os.path.isdir(company_path): 70 continue 71 72 for product in os.listdir(company_path): 73 product_path = os.path.join(company_path, product) 74 config_path = os.path.join(product_path, 'config.json') 75 76 if os.path.isfile(config_path): 77 info = read_json_file(config_path) 78 product_name = info.get('product_name') 79 if product_name is not None: 80 yield { 81 'company': company, 82 "name": product_name, 83 'product_config_path': product_path, 84 'product_path': product_path, 85 'version': info.get('version', '3.0'), 86 'os_level': info.get('type', "mini"), 87 'config': config_path, 88 'component_type': info.get('component_type', '') 89 } 90 bip_path = config.built_in_product_path 91 for item in os.listdir(bip_path): 92 if item[0] in ".": 93 continue 94 else: 95 product_name = item[0:-len('.json')] if item.endswith('.json') else item 96 config_path = os.path.join(bip_path, item) 97 info = read_json_file(config_path) 98 yield { 99 'company': 'built-in', 100 "name": product_name, 101 'product_config_path': bip_path, 102 'product_path': bip_path, 103 'version': info.get('version', '2.0'), 104 'os_level': info.get('type', 'standard'), 105 'config': config_path, 106 'component_type': info.get('component_type', '') 107 } 108 109 @staticmethod 110 def get_device_info(product_json): 111 info = read_json_file(product_json) 112 config = Config() 113 version = info.get('version', '3.0') 114 115 if version == '2.0': 116 device_json = os.path.join(config.built_in_device_path, 117 f'{info["product_device"]}.json') 118 device_info = read_json_file(device_json) 119 return { 120 'board': device_info.get('device_name'), 121 'kernel': device_info.get('kernel_type', 'linux'), 122 'kernel_version': device_info.get('kernel_version'), 123 'company': device_info.get('device_company'), 124 'board_path': device_info.get('device_build_path'), 125 'target_cpu': device_info.get('target_cpu'), 126 'target_os': device_info.get('target_os') 127 } 128 elif version == '3.0': 129 device_company = info.get('device_company') 130 board = info.get('board') 131 _board_path = info.get('board_path') 132 if _board_path and os.path.exists( 133 os.path.join(config.root_path, _board_path)): 134 board_path = os.path.join(config.root_path, _board_path) 135 else: 136 board_path = os.path.join(config.root_path, 'device', 137 device_company, board) 138 # board and soc decoupling feature will add boards 139 # directory path here. 140 if not os.path.exists(board_path): 141 board_path = os.path.join(config.root_path, 'device', 142 'board', device_company, board) 143 board_config_path = None 144 if info.get('board_config_path'): 145 board_config_path = os.path.join(config.root_path, 146 info.get('board_config_path')) 147 148 return { 149 'board': info.get('board'), 150 'kernel': info.get('kernel_type'), 151 'kernel_version': info.get('kernel_version'), 152 'company': info.get('device_company'), 153 'board_path': board_path, 154 'board_config_path': board_config_path, 155 'target_cpu': info.get('target_cpu'), 156 'target_os': info.get('target_os') 157 } 158 else: 159 raise OHOSException(f'wrong version number in {product_json}') 160 161 @staticmethod 162 def get_features(product_json): 163 if not os.path.isfile(product_json): 164 raise OHOSException(f'features {product_json} not found') 165 166 config = Config() 167 # Get all inherit files 168 files = [os.path.join(config.root_path, file) for file in read_json_file(product_json).get('inherit', [])] 169 # Add the product config file to last with highest priority 170 files.append(product_json) 171 172 # Read all parts in order 173 all_parts = {} 174 for _file in files: 175 if not os.path.isfile(_file): 176 continue 177 _info = read_json_file(_file) 178 parts = _info.get('parts') 179 if parts: 180 all_parts.update(parts) 181 else: 182 # v3 config files 183 all_parts.update(get_vendor_parts_list(_info)) 184 185 # Get all features 186 features_list = [] 187 for part, val in all_parts.items(): 188 if "features" not in val: 189 continue 190 for key, val in val["features"].items(): 191 _item = '' 192 if isinstance(val, bool): 193 _item = f'{key}={str(val).lower()}' 194 elif isinstance(val, int): 195 _item = f'{key}={val}' 196 elif isinstance(val, str): 197 _item = f'{key}="{val}"' 198 else: 199 raise Exception( 200 "part feature '{key}:{val}' type not support.") 201 features_list.append(_item) 202 return features_list 203 204 @staticmethod 205 def get_components(product_json, subsystems): 206 if not os.path.isfile(product_json): 207 raise OHOSException(f'{product_json} not found') 208 209 components_dict = defaultdict(list) 210 product_data = read_json_file(product_json) 211 for subsystem in product_data.get('subsystems', []): 212 sname = subsystem.get('subsystem', '') 213 if not len(subsystems) or sname in subsystems: 214 components_dict[sname] += [ 215 comp['component'] 216 for comp in subsystem.get('components', []) 217 ] 218 219 return components_dict, product_data.get('board', ''),\ 220 product_data.get('kernel_type', '') 221 222 @staticmethod 223 def get_product_info(product_name, company=None): 224 for product_info in Product.get_products(): 225 cur_company = product_info['company'] 226 cur_product = product_info['name'] 227 if company: 228 if cur_company == company and cur_product == product_name: 229 return product_info 230 else: 231 if cur_product == product_name: 232 return product_info 233 234 raise OHOSException(f'product {product_name}@{company} not found') 235 236 @staticmethod 237 def product_menuconfig(): 238 product_path_dict = {} 239 company_separator = None 240 for product_info in Product.get_products(): 241 company = product_info['company'] 242 product = product_info['name'] 243 if company_separator is None or company_separator != company: 244 company_separator = company 245 product_key = Separator(company_separator) 246 product_path_dict[product_key] = None 247 248 product_path_dict['{}@{}'.format(product, company)] = product_info 249 250 if not len(product_path_dict): 251 raise OHOSException('no valid product found') 252 253 choices = [ 254 product if isinstance(product, Separator) else { 255 'name': product.split('@')[0], 256 'value': product.split('@')[1] 257 } for product in product_path_dict.keys() 258 ] 259 menu = Menuconfig() 260 product = menu.list_promt('product', 'Which product do you need?', 261 choices).get('product') 262 product_key = f'{product[0]}@{product[1]}' 263 return product_path_dict[product_key] 264