1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4# Copyright (c) 2024 Huawei Device Co., Ltd. 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 17import os 18import struct 19import sys 20 21 22def int_to_str(int_n): 23 buf = "" 24 i = 0 25 while i < 4: 26 a = ((int_n >> (3 - i) * 8) & 0xff) 27 if a != 0: 28 buf = buf + chr(a) 29 i = i + 1 30 return buf 31 32 33resolutions = {-2: "nodpi", -1: "anydpi", 120: "sdpi", 160: "mdpi", 213: "tvdpi", 240: "ldpi", 320: "xldpi", 34 480: "xxldpi", 640: "xxxldpi"} 35 36orientations = {0: "vertical", 1: "horizontal"} 37 38devices = {0: "phone", 1: "tablet", 2: "car", 3: "pc", 4: "tv", 5: "speaker", 6: "wearable", 7: "glasses", 8: "headset"} 39 40night_modes = {0: "dark", 1: "light"} 41 42 43def parse_limit_key(limit_key): 44 key_str = "" 45 key_ = limit_key 46 if key_ == "": 47 key_ = "base" 48 key_str = "base" 49 50 key_sets = key_.split("-") 51 last_key_type = -1 52 for key_item in key_sets: 53 if key_item == "base": 54 continue 55 key_s = key_item.split(":") 56 if int(key_s[0]) == 0 or int(key_s[0]) == 1 or int(key_s[0]) == 5: 57 i = int(key_s[1]) 58 if key_str == "": 59 key_str = key_str + int_to_str(i) 60 elif last_key_type == 0 or last_key_type == 1 or last_key_type == 5: 61 key_str = "{}_{}".format(key_str, int_to_str(i)) 62 else: 63 key_str = "{}-{}".format(key_str, int_to_str(i)) 64 last_key_type = int(key_s[0]) 65 elif int(key_s[0]) == 2: 66 k = int(key_s[1]) 67 if (k & 0x80000000) != 0: 68 a = (0xffffffff ^ k) + 1 69 k = -1 * a 70 if key_str == "": 71 key_str = key_str + resolutions.get(k) 72 else: 73 key_str = "{}-{}".format(key_str, resolutions.get(k)) 74 elif int(key_s[0]) == 3: 75 if key_str == "": 76 key_str = key_str + orientations.get(int(key_s[1])) 77 else: 78 key_str = "{}-{}".format(key_str, orientations.get(int(key_s[1]))) 79 elif int(key_s[0]) == 4: 80 if key_str == "": 81 key_str = key_str + devices.get(int(key_s[1])) 82 else: 83 key_str = "{}-{}".format(key_str, devices.get(int(key_s[1]))) 84 elif int(key_s[0]) == 6: 85 if key_str == "": 86 key_str = key_str + night_modes.get(int(key_s[1])) 87 else: 88 key_str = "{}-{}".format(key_str, night_modes.get(int(key_s[1]))) 89 elif int(key_s[0]) == 7: 90 i = int(key_s[1]) 91 if key_str == "": 92 key_str = "{}mcc{}".format(key_str, str(i)) 93 else: 94 key_str = "{}_mcc{}".format(key_str, str(i)) 95 elif int(key_s[0]) == 8: 96 i = int(key_s[1]) 97 if key_str == "": 98 key_str = "{}mnc{:0>2d}".format(key_str, i) 99 else: 100 key_str = "{}_mnc{:0>2d}".format(key_str, i) 101 else: 102 raise Exception("invalid key={}".format(str(int(key_s[0])))) 103 return key_str 104 105 106def open_new_resource_index(file_path): 107 if not os.path.exists(file_path): 108 raise Exception("not found:" + file_path) 109 110 with open(file_path, "rb") as fp_resource_index: 111 header = fp_resource_index.read(128) 112 length = fp_resource_index.read(4) 113 key_count = fp_resource_index.read(4) 114 pri_key_count = struct.unpack("i", key_count)[0] 115 116 index_one = 0 117 118 # keys 119 private_index = {} 120 while index_one < pri_key_count: 121 buf = fp_resource_index.read(4) 122 p_key_tag = struct.unpack("4s", buf)[0] 123 124 buf = fp_resource_index.read(4) 125 p_data_offset = struct.unpack("I", buf)[0] 126 127 buf = fp_resource_index.read(4) 128 p_key_count = struct.unpack("I", buf)[0] 129 130 i = 0 131 key_str = "" 132 while i < p_key_count: 133 buf = fp_resource_index.read(8) 134 p_key_type = struct.unpack("I", buf[0:4])[0] 135 p_value = struct.unpack("I", buf[4:8])[0] 136 if key_str == "": 137 key_str = "{}:{}".format(str(p_key_type), str(p_value)) 138 else: 139 key_str = "{}-{}:{}".format(key_str, str(p_key_type), str(p_value)) 140 i = i + 1 141 private_index[key_str] = p_data_offset 142 index_one = index_one + 1 143 144 # idss 145 c = 0 146 idss_cache = {} 147 while c < pri_key_count: 148 pos = fp_resource_index.tell() 149 idss_buf = fp_resource_index.read(4) 150 idss_tag = struct.unpack("4s", idss_buf)[0] 151 idss_buf = fp_resource_index.read(4) 152 idss_count = struct.unpack("I", idss_buf)[0] 153 i = 0 154 idss_index = {} 155 while i < idss_count: 156 buf = fp_resource_index.read(4) 157 p_id = struct.unpack("I", buf)[0] 158 buf = fp_resource_index.read(4) 159 p_offset = struct.unpack("I", buf)[0] 160 idss_index[p_id] = p_offset 161 i = i + 1 162 idss_cache[pos] = idss_index 163 c = c + 1 164 165 third_data = {} 166 d_data = {} 167 d_pos = fp_resource_index.tell() 168 d_buf = fp_resource_index.read(4) 169 while len(d_buf) > 0: 170 d_size = struct.unpack("I", d_buf)[0] 171 d_buf = fp_resource_index.read(d_size) 172 d_res_type = struct.unpack("I", d_buf[0:4])[0] 173 174 d_value_len_l = struct.unpack("B", d_buf[8:9])[0] 175 d_value_len_h = struct.unpack("B", d_buf[9:10])[0] 176 d_value_len = d_value_len_l + d_value_len_h * 256 177 d_value = "" 178 if d_res_type == 10 or d_res_type == 11 or d_res_type == 16 or d_res_type == 17 or d_res_type == 22: 179 tmp = d_buf[10:10 + d_value_len] 180 d_d_pos = 0 181 while d_d_pos < d_value_len - 1: 182 d_d_value_len_l = struct.unpack("B", tmp[0 + d_d_pos:1 + d_d_pos])[0] 183 d_d_value_len_h = struct.unpack("B", tmp[1 + d_d_pos:2 + d_d_pos])[0] 184 d_d_value_len = d_d_value_len_l + d_d_value_len_h * 256 185 d_value = "{}<{}>".format(d_value, str(tmp[2 + d_d_pos:2 + d_d_value_len + d_d_pos])) 186 d_d_pos = d_d_pos + 2 + d_d_value_len + 1 187 else: 188 d_value = d_buf[10:10 + d_value_len - 1].decode("utf-8") 189 190 d_name_len_l = struct.unpack("B", d_buf[10 + d_value_len:11 + d_value_len])[0] 191 d_name_len_h = struct.unpack("B", d_buf[11 + d_value_len:12 + d_value_len])[0] 192 d_name_len = d_name_len_l + d_name_len_h * 256 193 d_name = str(d_buf[12 + d_value_len:12 + d_value_len + d_name_len - 1].decode("utf-8")) 194 d_data[d_pos] = [d_value, d_name] 195 196 d_pos = fp_resource_index.tell() 197 d_buf = fp_resource_index.read(4) 198 199 for key_, key_offset in private_index.items(): 200 third_data[key_] = {} 201 idss_sets = idss_cache.get(key_offset) 202 for id_, offset in idss_sets.items(): 203 id_sets = d_data.get(offset) 204 third_data[key_][id_] = id_sets 205 return third_data 206 207 208def dump(file_path, out_path): 209 out_file = os.open(out_path, os.O_WRONLY | os.O_CREAT, 0o664) 210 third_data = open_new_resource_index(file_path) 211 for key_, ids_ in third_data.items(): 212 key_str = parse_limit_key(key_) 213 if "zh_CN" == key_str: 214 continue 215 os.write(out_file, str.encode("keyconfig:{}\n".format(key_))) 216 os.write(out_file, str.encode("{}\n".format(key_str))) 217 for id_, idsets in ids_.items(): 218 os.write(out_file, str.encode("id:{}, '{}' '{}'\n".format(str(id_), idsets[0], str(idsets[1])))) 219 os.close(out_file) 220