Loading tools/fs_config/fs_config_generator.py +120 −60 Original line number Diff line number Diff line Loading @@ -98,8 +98,20 @@ class AID(object): value (str) The User Id (uid) of the associate define. found (str) The file it was found in, can be None. normalized_value (str): Same as value, but base 10. friendly (str): The friendly name of aid. """ PREFIX = 'AID_' # Some of the AIDS like AID_MEDIA_EX had names like mediaex # list a map of things to fixup until we can correct these # at a later date. _FIXUPS = { 'media_drm': 'mediadrm', 'media_ex': 'mediaex', 'media_codec': 'mediacodec' } def __init__(self, identifier, value, found): """ Args: Loading @@ -116,6 +128,39 @@ class AID(object): self.found = found self.normalized_value = str(int(value, 0)) # Where we calculate the friendly name friendly = identifier[len(AID.PREFIX):].lower() self.friendly = AID._fixup_friendly(friendly) @staticmethod def is_friendly(name): """Determines if an AID is a freindly name or C define. For example if name is AID_SYSTEM it returns false, if name was system, it would return true. Returns: True if name is a friendly name False otherwise. """ return not name.startswith(AID.PREFIX) @staticmethod def _fixup_friendly(friendly): """Fixup friendly names that historically don't follow the convention. Args: friendly (str): The friendly name. Returns: The fixedup friendly name as a str. """ if friendly in AID._FIXUPS: return AID._FIXUPS[friendly] return friendly class FSConfig(object): """Represents a filesystem config array entry. Loading Loading @@ -160,22 +205,12 @@ class AIDHeaderParser(object): """ _SKIPWORDS = ['UNUSED'] _AID_KW = 'AID_' _AID_DEFINE = re.compile(r'\s*#define\s+%s.*' % _AID_KW) _AID_DEFINE = re.compile(r'\s*#define\s+%s.*' % AID.PREFIX) _OEM_START_KW = 'START' _OEM_END_KW = 'END' _OEM_RANGE = re.compile('AID_OEM_RESERVED_[0-9]*_{0,1}(%s|%s)' % (_OEM_START_KW, _OEM_END_KW)) # Some of the AIDS like AID_MEDIA_EX had names like mediaex # list a map of things to fixup until we can correct these # at a later date. _FIXUPS = { 'media_drm': 'mediadrm', 'media_ex': 'mediaex', 'media_codec': 'mediacodec' } def __init__(self, aid_header): """ Args: Loading Loading @@ -240,19 +275,18 @@ class AIDHeaderParser(object): ValueError: With message set to indicate the error. """ # friendly name name = AIDHeaderParser._convert_friendly(identifier) aid = AID(identifier, value, self._aid_header) # duplicate name if name in self._aid_name_to_value: if aid.friendly in self._aid_name_to_value: raise ValueError('Duplicate aid "%s"' % identifier) if value in self._aid_value_to_name: raise ValueError('Duplicate aid value "%u" for %s' % value, identifier) self._aid_name_to_value[name] = AID(identifier, value, self._aid_header) self._aid_value_to_name[value] = name self._aid_name_to_value[aid.friendly] = aid self._aid_value_to_name[value] = aid.friendly def _handle_oem_range(self, identifier, value): """Handle an OEM range C #define. Loading Loading @@ -363,7 +397,7 @@ class AIDHeaderParser(object): Returns: A list of AID() objects. """ return self._aid_name_to_value return self._aid_name_to_value.values() @staticmethod def _convert_lst_to_tup(name, lst): Loading @@ -385,25 +419,6 @@ class AIDHeaderParser(object): return tuple(lst) @staticmethod def _convert_friendly(identifier): """ Translate AID_FOO_BAR to foo_bar (ie name) Args: identifier (str): The name of the #define. Returns: The friendly name as a str. """ name = identifier[len(AIDHeaderParser._AID_KW):].lower() if name in AIDHeaderParser._FIXUPS: return AIDHeaderParser._FIXUPS[name] return name @staticmethod def _is_oem_range(aid): """Detects if a given aid is within the reserved OEM range. Loading Loading @@ -449,8 +464,7 @@ class FSConfigFileParser(object): # Since _AID_PREFIX is within the set of _AID_MATCH the error logic only # checks end, if you change this, you may have to update the error # detection code. _AID_PREFIX = 'AID_' _AID_MATCH = re.compile('%s[A-Z0-9_]+' % _AID_PREFIX) _AID_MATCH = re.compile('%s[A-Z0-9_]+' % AID.PREFIX) _AID_ERR_MSG = 'Expecting upper case, a number or underscore' # list of handler to required options, used to identify the Loading Loading @@ -560,7 +574,7 @@ class FSConfigFileParser(object): self._seen_aids[0]) match = FSConfigFileParser._AID_MATCH.match(section_name) invalid = match.end() if match else len(FSConfigFileParser._AID_PREFIX) invalid = match.end() if match else len(AID.PREFIX) if invalid != len(section_name): tmp_errmsg = ('Invalid characters in AID section at "%d" for: "%s"' % (invalid, FSConfigFileParser._AID_ERR_MSG)) Loading Loading @@ -861,6 +875,13 @@ class FSConfigGen(BaseGenerator): _FILE_COMMENT = '// Defined in file: \"%s\"' def __init__(self, *args, **kwargs): BaseGenerator.__init__(args, kwargs) self._oem_parser = None self._base_parser = None self._friendly_to_aid = None def add_opts(self, opt_group): opt_group.add_argument( Loading @@ -874,19 +895,46 @@ class FSConfigGen(BaseGenerator): def __call__(self, args): hdr = AIDHeaderParser(args['aid_header']) oem_ranges = hdr.oem_ranges self._base_parser = AIDHeaderParser(args['aid_header']) self._oem_parser = FSConfigFileParser(args['fsconfig'], self._base_parser.oem_ranges) base_aids = self._base_parser.aids oem_aids = self._oem_parser.aids parser = FSConfigFileParser(args['fsconfig'], oem_ranges) FSConfigGen._generate(parser.files, parser.dirs, parser.aids) # Detect name collisions on AIDs. Since friendly works as the # identifier for collision testing and we need friendly later on for # name resolution, just calculate and use friendly. # {aid.friendly: aid for aid in base_aids} base_friendly = {aid.friendly: aid for aid in base_aids} oem_friendly = {aid.friendly: aid for aid in oem_aids} @staticmethod def _to_fs_entry(fs_config): """ Given an FSConfig entry, converts it to a proper array entry for the array entry. base_set = set(base_friendly.keys()) oem_set = set(oem_friendly.keys()) common = base_set & oem_set if len(common) > 0: emsg = 'Following AID Collisions detected for: \n' for friendly in common: base = base_friendly[friendly] oem = oem_friendly[friendly] emsg += ( 'Identifier: "%s" Friendly Name: "%s" ' 'found in file "%s" and "%s"' % (base.identifier, base.friendly, base.found, oem.found)) sys.exit(emsg) self._friendly_to_aid = oem_friendly self._friendly_to_aid.update(base_friendly) self._generate() def _to_fs_entry(self, fs_config): """Converts an FSConfig entry to an fs entry. { mode, user, group, caps, "path" }, Prints '{ mode, user, group, caps, "path" },'. Calls sys.exit() on error. Args: fs_config (FSConfig): The entry to convert to Loading @@ -901,6 +949,19 @@ class FSConfigGen(BaseGenerator): caps = fs_config.caps path = fs_config.path emsg = 'Cannot convert friendly name "%s" to identifier!' # remap friendly names to identifier names if AID.is_friendly(user): if user not in self._friendly_to_aid: sys.exit(emsg % user) user = self._friendly_to_aid[user].identifier if AID.is_friendly(group): if group not in self._friendly_to_aid: sys.exit(emsg % group) group = self._friendly_to_aid[group].identifier fmt = '{ %s, %s, %s, %s, "%s" },' expanded = fmt % (mode, user, group, caps, path) Loading @@ -910,15 +971,11 @@ class FSConfigGen(BaseGenerator): @staticmethod def _gen_inc(): """ Generate the include header lines and print to stdout. Internal use only. """ """Generate the include header lines and print to stdout.""" for include in FSConfigGen._INCLUDES: print '#include %s' % include @staticmethod def _generate(files, dirs, aids): def _generate(self): """Generates an OEM android_filesystem_config.h header file to stdout. Args: Loading @@ -933,6 +990,10 @@ class FSConfigGen(BaseGenerator): FSConfigGen._gen_inc() print dirs = self._oem_parser.dirs files = self._oem_parser.files aids = self._oem_parser.aids are_dirs = len(dirs) > 0 are_files = len(files) > 0 are_aids = len(aids) > 0 Loading @@ -952,13 +1013,12 @@ class FSConfigGen(BaseGenerator): print FSConfigGen._DEFINE_NO_FILES + '\n' if not are_files and not are_dirs and not are_aids: print FSConfigGen._DEFAULT_WARNING return if are_files: print FSConfigGen._OPEN_FILE_STRUCT for fs_config in files: FSConfigGen._to_fs_entry(fs_config) self._to_fs_entry(fs_config) if not are_dirs: print FSConfigGen._IFDEF_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS Loading @@ -971,7 +1031,7 @@ class FSConfigGen(BaseGenerator): if are_dirs: print FSConfigGen._OPEN_DIR_STRUCT for dir_entry in dirs: FSConfigGen._to_fs_entry(dir_entry) self._to_fs_entry(dir_entry) print FSConfigGen._CLOSE_FILE_STRUCT Loading Loading @@ -1019,8 +1079,8 @@ class AIDArrayGen(BaseGenerator): print print AIDArrayGen._OPEN_ID_ARRAY for name, aid in hdr.aids.iteritems(): print AIDArrayGen._ID_ENTRY % (name, aid.identifier) for aid in hdr.aids: print AIDArrayGen._ID_ENTRY % (aid.friendly, aid.identifier) print AIDArrayGen._CLOSE_FILE_STRUCT print Loading Loading
tools/fs_config/fs_config_generator.py +120 −60 Original line number Diff line number Diff line Loading @@ -98,8 +98,20 @@ class AID(object): value (str) The User Id (uid) of the associate define. found (str) The file it was found in, can be None. normalized_value (str): Same as value, but base 10. friendly (str): The friendly name of aid. """ PREFIX = 'AID_' # Some of the AIDS like AID_MEDIA_EX had names like mediaex # list a map of things to fixup until we can correct these # at a later date. _FIXUPS = { 'media_drm': 'mediadrm', 'media_ex': 'mediaex', 'media_codec': 'mediacodec' } def __init__(self, identifier, value, found): """ Args: Loading @@ -116,6 +128,39 @@ class AID(object): self.found = found self.normalized_value = str(int(value, 0)) # Where we calculate the friendly name friendly = identifier[len(AID.PREFIX):].lower() self.friendly = AID._fixup_friendly(friendly) @staticmethod def is_friendly(name): """Determines if an AID is a freindly name or C define. For example if name is AID_SYSTEM it returns false, if name was system, it would return true. Returns: True if name is a friendly name False otherwise. """ return not name.startswith(AID.PREFIX) @staticmethod def _fixup_friendly(friendly): """Fixup friendly names that historically don't follow the convention. Args: friendly (str): The friendly name. Returns: The fixedup friendly name as a str. """ if friendly in AID._FIXUPS: return AID._FIXUPS[friendly] return friendly class FSConfig(object): """Represents a filesystem config array entry. Loading Loading @@ -160,22 +205,12 @@ class AIDHeaderParser(object): """ _SKIPWORDS = ['UNUSED'] _AID_KW = 'AID_' _AID_DEFINE = re.compile(r'\s*#define\s+%s.*' % _AID_KW) _AID_DEFINE = re.compile(r'\s*#define\s+%s.*' % AID.PREFIX) _OEM_START_KW = 'START' _OEM_END_KW = 'END' _OEM_RANGE = re.compile('AID_OEM_RESERVED_[0-9]*_{0,1}(%s|%s)' % (_OEM_START_KW, _OEM_END_KW)) # Some of the AIDS like AID_MEDIA_EX had names like mediaex # list a map of things to fixup until we can correct these # at a later date. _FIXUPS = { 'media_drm': 'mediadrm', 'media_ex': 'mediaex', 'media_codec': 'mediacodec' } def __init__(self, aid_header): """ Args: Loading Loading @@ -240,19 +275,18 @@ class AIDHeaderParser(object): ValueError: With message set to indicate the error. """ # friendly name name = AIDHeaderParser._convert_friendly(identifier) aid = AID(identifier, value, self._aid_header) # duplicate name if name in self._aid_name_to_value: if aid.friendly in self._aid_name_to_value: raise ValueError('Duplicate aid "%s"' % identifier) if value in self._aid_value_to_name: raise ValueError('Duplicate aid value "%u" for %s' % value, identifier) self._aid_name_to_value[name] = AID(identifier, value, self._aid_header) self._aid_value_to_name[value] = name self._aid_name_to_value[aid.friendly] = aid self._aid_value_to_name[value] = aid.friendly def _handle_oem_range(self, identifier, value): """Handle an OEM range C #define. Loading Loading @@ -363,7 +397,7 @@ class AIDHeaderParser(object): Returns: A list of AID() objects. """ return self._aid_name_to_value return self._aid_name_to_value.values() @staticmethod def _convert_lst_to_tup(name, lst): Loading @@ -385,25 +419,6 @@ class AIDHeaderParser(object): return tuple(lst) @staticmethod def _convert_friendly(identifier): """ Translate AID_FOO_BAR to foo_bar (ie name) Args: identifier (str): The name of the #define. Returns: The friendly name as a str. """ name = identifier[len(AIDHeaderParser._AID_KW):].lower() if name in AIDHeaderParser._FIXUPS: return AIDHeaderParser._FIXUPS[name] return name @staticmethod def _is_oem_range(aid): """Detects if a given aid is within the reserved OEM range. Loading Loading @@ -449,8 +464,7 @@ class FSConfigFileParser(object): # Since _AID_PREFIX is within the set of _AID_MATCH the error logic only # checks end, if you change this, you may have to update the error # detection code. _AID_PREFIX = 'AID_' _AID_MATCH = re.compile('%s[A-Z0-9_]+' % _AID_PREFIX) _AID_MATCH = re.compile('%s[A-Z0-9_]+' % AID.PREFIX) _AID_ERR_MSG = 'Expecting upper case, a number or underscore' # list of handler to required options, used to identify the Loading Loading @@ -560,7 +574,7 @@ class FSConfigFileParser(object): self._seen_aids[0]) match = FSConfigFileParser._AID_MATCH.match(section_name) invalid = match.end() if match else len(FSConfigFileParser._AID_PREFIX) invalid = match.end() if match else len(AID.PREFIX) if invalid != len(section_name): tmp_errmsg = ('Invalid characters in AID section at "%d" for: "%s"' % (invalid, FSConfigFileParser._AID_ERR_MSG)) Loading Loading @@ -861,6 +875,13 @@ class FSConfigGen(BaseGenerator): _FILE_COMMENT = '// Defined in file: \"%s\"' def __init__(self, *args, **kwargs): BaseGenerator.__init__(args, kwargs) self._oem_parser = None self._base_parser = None self._friendly_to_aid = None def add_opts(self, opt_group): opt_group.add_argument( Loading @@ -874,19 +895,46 @@ class FSConfigGen(BaseGenerator): def __call__(self, args): hdr = AIDHeaderParser(args['aid_header']) oem_ranges = hdr.oem_ranges self._base_parser = AIDHeaderParser(args['aid_header']) self._oem_parser = FSConfigFileParser(args['fsconfig'], self._base_parser.oem_ranges) base_aids = self._base_parser.aids oem_aids = self._oem_parser.aids parser = FSConfigFileParser(args['fsconfig'], oem_ranges) FSConfigGen._generate(parser.files, parser.dirs, parser.aids) # Detect name collisions on AIDs. Since friendly works as the # identifier for collision testing and we need friendly later on for # name resolution, just calculate and use friendly. # {aid.friendly: aid for aid in base_aids} base_friendly = {aid.friendly: aid for aid in base_aids} oem_friendly = {aid.friendly: aid for aid in oem_aids} @staticmethod def _to_fs_entry(fs_config): """ Given an FSConfig entry, converts it to a proper array entry for the array entry. base_set = set(base_friendly.keys()) oem_set = set(oem_friendly.keys()) common = base_set & oem_set if len(common) > 0: emsg = 'Following AID Collisions detected for: \n' for friendly in common: base = base_friendly[friendly] oem = oem_friendly[friendly] emsg += ( 'Identifier: "%s" Friendly Name: "%s" ' 'found in file "%s" and "%s"' % (base.identifier, base.friendly, base.found, oem.found)) sys.exit(emsg) self._friendly_to_aid = oem_friendly self._friendly_to_aid.update(base_friendly) self._generate() def _to_fs_entry(self, fs_config): """Converts an FSConfig entry to an fs entry. { mode, user, group, caps, "path" }, Prints '{ mode, user, group, caps, "path" },'. Calls sys.exit() on error. Args: fs_config (FSConfig): The entry to convert to Loading @@ -901,6 +949,19 @@ class FSConfigGen(BaseGenerator): caps = fs_config.caps path = fs_config.path emsg = 'Cannot convert friendly name "%s" to identifier!' # remap friendly names to identifier names if AID.is_friendly(user): if user not in self._friendly_to_aid: sys.exit(emsg % user) user = self._friendly_to_aid[user].identifier if AID.is_friendly(group): if group not in self._friendly_to_aid: sys.exit(emsg % group) group = self._friendly_to_aid[group].identifier fmt = '{ %s, %s, %s, %s, "%s" },' expanded = fmt % (mode, user, group, caps, path) Loading @@ -910,15 +971,11 @@ class FSConfigGen(BaseGenerator): @staticmethod def _gen_inc(): """ Generate the include header lines and print to stdout. Internal use only. """ """Generate the include header lines and print to stdout.""" for include in FSConfigGen._INCLUDES: print '#include %s' % include @staticmethod def _generate(files, dirs, aids): def _generate(self): """Generates an OEM android_filesystem_config.h header file to stdout. Args: Loading @@ -933,6 +990,10 @@ class FSConfigGen(BaseGenerator): FSConfigGen._gen_inc() print dirs = self._oem_parser.dirs files = self._oem_parser.files aids = self._oem_parser.aids are_dirs = len(dirs) > 0 are_files = len(files) > 0 are_aids = len(aids) > 0 Loading @@ -952,13 +1013,12 @@ class FSConfigGen(BaseGenerator): print FSConfigGen._DEFINE_NO_FILES + '\n' if not are_files and not are_dirs and not are_aids: print FSConfigGen._DEFAULT_WARNING return if are_files: print FSConfigGen._OPEN_FILE_STRUCT for fs_config in files: FSConfigGen._to_fs_entry(fs_config) self._to_fs_entry(fs_config) if not are_dirs: print FSConfigGen._IFDEF_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS Loading @@ -971,7 +1031,7 @@ class FSConfigGen(BaseGenerator): if are_dirs: print FSConfigGen._OPEN_DIR_STRUCT for dir_entry in dirs: FSConfigGen._to_fs_entry(dir_entry) self._to_fs_entry(dir_entry) print FSConfigGen._CLOSE_FILE_STRUCT Loading Loading @@ -1019,8 +1079,8 @@ class AIDArrayGen(BaseGenerator): print print AIDArrayGen._OPEN_ID_ARRAY for name, aid in hdr.aids.iteritems(): print AIDArrayGen._ID_ENTRY % (name, aid.identifier) for aid in hdr.aids: print AIDArrayGen._ID_ENTRY % (aid.friendly, aid.identifier) print AIDArrayGen._CLOSE_FILE_STRUCT print Loading