Preserve <uses-library> order in dexpreopt.config files.

Library order is important because it is used to construct class loader
context, which is then written into OAT/ODEX files and chacked against
class loader context constructed by PackageManager on the device. If the
orders are different, dexpreopted code is rejected.

This CL fixes a few problems that caused reordering:

- 'filter' function arguments are swapped so that patterns list comes
  first, and the library list second

- JSON representation of class loader context is changed to avoid
  unmarshaling it to Go maps, which may reorder keys

- library list is no longer sorted (it's unclear why it was sorted)

Bug: 132357300
Test: lunch cf_x86_64_phone-userdebug && m && launch_cvd \
      adb wait-for-device && adb root && adb logcat \
      | grep -E 'ClassLoaderContext [a-z ]+ mismatch'
      # empty grep output, no errors
Change-Id: Ie76996d497e60da0948f1879d6db589ff3e968a2
This commit is contained in:
Ulya Trafimovich
2021-02-11 16:58:25 +00:00
parent b976c07d85
commit 8edad8f7a3
3 changed files with 19 additions and 15 deletions

View File

@@ -67,24 +67,25 @@ def main():
# the loop in case this changes in the future.
for sdk_ver in clc_map:
clcs = clc_map[sdk_ver]
clcs2 = OrderedDict()
for lib in clcs:
clc = clcs[lib]
clcs2 = []
for clc in clcs:
lib = clc['Name']
if lib in uses_libs:
ulib = uses_libs[lib]
# The real <uses-library> name (may be different from the module name).
clc['Name'] = ulib['ProvidesUsesLibrary']
# On-device (install) path to the dependency DEX jar file.
clc['Device'] = ulib['DexLocation']
# CLC of the dependency becomes a subcontext. We only need sub-CLC for
# 'any' version because all other versions are for compatibility
# libraries, which exist only for apps and not for libraries.
clc['Subcontexts'] = ulib['ClassLoaderContexts'].get('any')
# Patch the library name in the CLC as well.
clcs2[ulib['ProvidesUsesLibrary']] = clc
else:
# dexpreopt.config for this <uses-library> is not among the script
# arguments, which may be the case with compatibility libraries that
# don't need patching anyway. Just use the original CLC.
clcs2[lib] = clc
pass
clcs2.append(clc)
clc_map2[sdk_ver] = clcs2
# Overwrite the original class loader context with the patched one.