summaryrefslogtreecommitdiff
path: root/tools/hiddenapi/generate_hiddenapi_lists.py
diff options
context:
space:
mode:
authorDavid Brazdil <dbrazdil@google.com>2018-09-11 11:09:01 +0100
committerDavid Brazdil <dbrazdil@google.com>2018-09-11 11:43:07 +0100
commit4a55eebf26a5366de302578f76947e7c05305a22 (patch)
tree2f1811bb36030f2252a422b3bca1b3a7f6762f0a /tools/hiddenapi/generate_hiddenapi_lists.py
parent60ff003a9d988ba7459906b131fa5718b80dc093 (diff)
Revert "Check in P dark greylist, use it for hidden API list generation"
This reverts commit 3cc74c71ef907a76547424aea6597f7b2907e9fb. We saw app crashes due stricter classification of non-SDK APIs. Bug: 115284625 Bug: 113881436 Test: phone boots Change-Id: I689d0fbf66fabeffa5032e13f2f1f314c50b6cc5
Diffstat (limited to 'tools/hiddenapi/generate_hiddenapi_lists.py')
-rwxr-xr-xtools/hiddenapi/generate_hiddenapi_lists.py88
1 files changed, 64 insertions, 24 deletions
diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py
index c5fcb63624c5..6c46e67be63d 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists.py
@@ -45,12 +45,9 @@ def get_args():
'--input-whitelists', nargs='*',
help='Lists of members to force on whitelist')
parser.add_argument(
- '--input-light-greylists', nargs='*',
+ '--input-greylists', nargs='*',
help='Lists of members to force on light greylist')
parser.add_argument(
- '--input-dark-greylists', nargs='*',
- help='Lists of members to force on dark greylist')
- parser.add_argument(
'--input-blacklists', nargs='*',
help='Lists of members to force on blacklist')
parser.add_argument('--output-whitelist', required=True)
@@ -83,31 +80,61 @@ def write_lines(filename, lines):
with open(filename, 'w') as f:
f.writelines(lines)
-def move_between_sets(subset, src, dst, source = "<unknown>", ignoreMissing = False):
+def move_between_sets(subset, src, dst, source = "<unknown>"):
"""Removes a subset of elements from one set and add it to another.
Args:
subset (set): The subset of `src` to be moved from `src` to `dst`.
src (set): Source set. Must be a superset of `subset`.
dst (set): Destination set. Must be disjoint with `subset`.
- source (string): Name of the data source.
- ignoreMissing (bool): If true, do not check whether `src` is a superset of `subset`.
"""
- if ignoreMissing:
- # Some entries in `subset` may not be in `src`. Remove such entries first.
- subset.intersection_update(src)
- else:
- assert src.issuperset(subset), (
- "Error processing: {}\n"
- "The following entries were not found:\n"
- "{}"
- "Please visit go/hiddenapi for more information.").format(
- source, "".join(map(lambda x: " " + str(x), subset.difference(src))))
- assert dst.isdisjoint(subset)
+ assert src.issuperset(subset), (
+ "Error processing: {}\n"
+ "The following entries were not found:\n"
+ "{}"
+ "Please visit go/hiddenapi for more information.").format(
+ source, "".join(map(lambda x: " " + str(x), subset.difference(src))))
+ assert dst.isdisjoint(subset)
# Order matters if `src` and `subset` are the same object.
dst.update(subset)
src.difference_update(subset)
+def get_package_name(signature):
+ """Returns the package name prefix of a class member signature.
+
+ Example: "Ljava/lang/String;->hashCode()J" --> "Ljava/lang/"
+
+ Args:
+ signature (string): Member signature
+
+ Returns
+ string: Package name of the given member
+ """
+ class_name_end = signature.find("->")
+ assert class_name_end != -1, "Invalid signature: {}".format(signature)
+ package_name_end = signature.rfind("/", 0, class_name_end)
+ assert package_name_end != -1, "Invalid signature: {}".format(signature)
+ return signature[:package_name_end + 1]
+
+def all_package_names(*args):
+ """Returns a set of packages names in given lists of member signatures.
+
+ Example: args = [ set([ "Lpkg1/ClassA;->foo()V", "Lpkg2/ClassB;->bar()J" ]),
+ set([ "Lpkg1/ClassC;->baz()Z" ]) ]
+ return value = set([ "Lpkg1/", "Lpkg2" ])
+
+ Args:
+ *args (list): List of sets to iterate over and extract the package names
+ of its elements (member signatures)
+
+ Returns:
+ set: All package names extracted from the given lists of signatures.
+ """
+ packages = set()
+ for arg in args:
+ packages = packages.union(map(get_package_name, arg))
+ return packages
+
def move_all(src, dst):
"""Moves all elements of one set to another.
@@ -117,7 +144,7 @@ def move_all(src, dst):
"""
move_between_sets(src, src, dst)
-def move_from_files(filenames, src, dst, ignoreMissing = False):
+def move_from_files(filenames, src, dst):
"""Loads member signatures from a list of files and moves them to a given set.
Opens files in `filenames`, reads all their lines and moves those from `src`
@@ -130,7 +157,7 @@ def move_from_files(filenames, src, dst, ignoreMissing = False):
"""
if filenames:
for filename in filenames:
- move_between_sets(set(read_lines(filename)), src, dst, filename, ignoreMissing)
+ move_between_sets(set(read_lines(filename)), src, dst, filename)
def move_serialization(src, dst):
"""Moves all members matching serialization API signatures between given sets.
@@ -152,6 +179,17 @@ def move_serialization(src, dst):
regex = re.compile(r'.*->(' + '|'.join(serialization_patterns) + r')$')
move_between_sets(filter(lambda api: regex.match(api), src), src, dst)
+def move_from_packages(packages, src, dst):
+ """Moves all members of given package names from one set to another.
+
+ Args:
+ packages (list): List of string package names.
+ src (set): Set that will be searched for API matching one of the given
+ package names. Surch API will be removed from the set.
+ dst (set): Set that matching API will be moved to.
+ """
+ move_between_sets(filter(lambda api: get_package_name(api) in packages, src), src, dst)
+
def main(argv):
args = get_args()
@@ -171,15 +209,17 @@ def main(argv):
# Read all files which manually assign members to specific lists.
move_from_files(args.input_whitelists, uncategorized, whitelist)
- move_from_files(args.input_light_greylists, uncategorized, light_greylist)
+ move_from_files(args.input_greylists, uncategorized, light_greylist)
move_from_files(args.input_blacklists, uncategorized, blacklist)
# Iterate over all uncategorized members and move serialization API to light greylist.
move_serialization(uncategorized, light_greylist)
- # Read dark greylist inputs and move all entries to dark greylist.
- # Note that the input is the list from P, so we will ignore missing entries.
- move_from_files(args.input_dark_greylists, uncategorized, dark_greylist, ignoreMissing=True)
+ # Extract package names of members from whitelist and light greylist, which
+ # are assumed to have been finalized at this point. Assign all uncategorized
+ # members from the same packages to the dark greylist.
+ dark_greylist_packages = all_package_names(whitelist, light_greylist)
+ move_from_packages(dark_greylist_packages, uncategorized, dark_greylist)
# Assign all uncategorized members to the blacklist.
move_all(uncategorized, blacklist)