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:
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.
"""
_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:
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.
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):
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.
# 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
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))
_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(
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
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)
@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:
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
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
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
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