All these scripts are now python3-only, they don't need this. Test: Presubmits Change-Id: Id2b9db26a537f6d70e874a0ae2ceb0927cbdce7d
136 lines
4.4 KiB
Python
Executable file
136 lines
4.4 KiB
Python
Executable file
#!/usr/bin/env python
|
|
#
|
|
# Copyright (C) 2020 The Android Open Source Project
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
#
|
|
"""A tool for constructing class loader context."""
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
|
|
from manifest import compare_version_gt
|
|
|
|
|
|
def parse_args(args):
|
|
"""Parse commandline arguments."""
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument(
|
|
'--target-sdk-version',
|
|
default='',
|
|
dest='sdk',
|
|
help='specify target SDK version (as it appears in the manifest)')
|
|
parser.add_argument(
|
|
'--context-json',
|
|
default='',
|
|
dest='context_json',
|
|
)
|
|
parser.add_argument(
|
|
'--product-packages',
|
|
default='',
|
|
dest='product_packages_file',
|
|
)
|
|
return parser.parse_args(args)
|
|
|
|
|
|
# Special keyword that means that the context should be added to class loader
|
|
# context regardless of the target SDK version.
|
|
any_sdk = 'any'
|
|
|
|
context_sep = '#'
|
|
|
|
|
|
def encode_class_loader(context, product_packages):
|
|
host_sub_contexts, target_sub_contexts = encode_class_loaders(
|
|
context['Subcontexts'], product_packages)
|
|
|
|
return ('PCL[%s]%s' % (context['Host'], host_sub_contexts),
|
|
'PCL[%s]%s' % (context['Device'], target_sub_contexts))
|
|
|
|
|
|
def encode_class_loaders(contexts, product_packages):
|
|
host_contexts = []
|
|
target_contexts = []
|
|
|
|
for context in contexts:
|
|
if not context['Optional'] or context['Name'] in product_packages:
|
|
host_context, target_context = encode_class_loader(
|
|
context, product_packages)
|
|
host_contexts.append(host_context)
|
|
target_contexts.append(target_context)
|
|
|
|
if host_contexts:
|
|
return ('{%s}' % context_sep.join(host_contexts),
|
|
'{%s}' % context_sep.join(target_contexts))
|
|
else:
|
|
return '', ''
|
|
|
|
|
|
def construct_context_args(target_sdk, context_json, product_packages):
|
|
all_contexts = []
|
|
|
|
# CLC for different SDK versions should come in specific order that agrees
|
|
# with PackageManager. Since PackageManager processes SDK versions in
|
|
# ascending order and prepends compatibility libraries at the front, the
|
|
# required order is descending, except for any_sdk that has numerically
|
|
# the largest order, but must be the last one. Example of correct order:
|
|
# [30, 29, 28, any_sdk]. There are Python tests to ensure that someone
|
|
# doesn't change this by accident, but there is no way to guard against
|
|
# changes in the PackageManager, except for grepping logcat on the first
|
|
# boot for absence of the following messages:
|
|
#
|
|
# `logcat | grep -E 'ClassLoaderContext [a-z ]+ mismatch`
|
|
|
|
for sdk, contexts in sorted(
|
|
((sdk, contexts)
|
|
for sdk, contexts in context_json.items()
|
|
if sdk != any_sdk and compare_version_gt(sdk, target_sdk)),
|
|
key=lambda item: int(item[0]), reverse=True):
|
|
all_contexts += contexts
|
|
|
|
if any_sdk in context_json:
|
|
all_contexts += context_json[any_sdk]
|
|
|
|
host_contexts, target_contexts = encode_class_loaders(
|
|
all_contexts, product_packages)
|
|
|
|
return (
|
|
'class_loader_context_arg=--class-loader-context=PCL[]%s ; ' %
|
|
host_contexts +
|
|
'stored_class_loader_context_arg='
|
|
'--stored-class-loader-context=PCL[]%s'
|
|
% target_contexts)
|
|
|
|
|
|
def main():
|
|
"""Program entry point."""
|
|
try:
|
|
args = parse_args(sys.argv[1:])
|
|
if not args.sdk:
|
|
raise SystemExit('target sdk version is not set')
|
|
|
|
context_json = json.loads(args.context_json)
|
|
with open(args.product_packages_file, 'r') as f:
|
|
product_packages = set(line.strip() for line in f if line.strip())
|
|
|
|
print(construct_context_args(args.sdk, context_json, product_packages))
|
|
|
|
# pylint: disable=broad-except
|
|
except Exception as err:
|
|
print('error: ' + str(err), file=sys.stderr)
|
|
sys.exit(-1)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|