Merge "Update language to comply with Android's inclusive language guidance" am: 31be55091f am: df5b66050c

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1374279

Change-Id: I9bff1926c2878da6b20f67482683afccb21123f4
This commit is contained in:
Andrei-Valentin Onea
2020-07-30 12:42:53 +00:00
committed by Automerger Merge Worker
2 changed files with 113 additions and 53 deletions

View File

@@ -13,9 +13,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
""" """Generate API lists for non-SDK API enforcement."""
Generate API lists for non-SDK API enforcement.
"""
import argparse import argparse
from collections import defaultdict from collections import defaultdict
import functools import functools
@@ -24,27 +22,47 @@ import re
import sys import sys
# Names of flags recognized by the `hiddenapi` tool. # Names of flags recognized by the `hiddenapi` tool.
FLAG_WHITELIST = "whitelist" FLAG_SDK = 'sdk'
FLAG_GREYLIST = "greylist" FLAG_UNSUPPORTED = 'unsupported'
FLAG_BLACKLIST = "blacklist" FLAG_BLOCKED = 'blocked'
FLAG_GREYLIST_MAX_O = "greylist-max-o" FLAG_MAX_TARGET_O = 'max-target-o'
FLAG_GREYLIST_MAX_P = "greylist-max-p" FLAG_MAX_TARGET_P = 'max-target-p'
FLAG_GREYLIST_MAX_Q = "greylist-max-q" FLAG_MAX_TARGET_Q = 'max-target-q'
FLAG_GREYLIST_MAX_R = "greylist-max-r" FLAG_MAX_TARGET_R = 'max-target-r'
FLAG_CORE_PLATFORM_API = "core-platform-api" FLAG_CORE_PLATFORM_API = 'core-platform-api'
FLAG_PUBLIC_API = "public-api" FLAG_PUBLIC_API = 'public-api'
FLAG_SYSTEM_API = "system-api" FLAG_SYSTEM_API = 'system-api'
FLAG_TEST_API = "test-api" FLAG_TEST_API = 'test-api'
OLD_FLAG_SDK = "whitelist"
OLD_FLAG_UNSUPPORTED = "greylist"
OLD_FLAG_BLOCKED = "blacklist"
OLD_FLAG_MAX_TARGET_O = "greylist-max-o"
OLD_FLAG_MAX_TARGET_P = "greylist-max-p"
OLD_FLAG_MAX_TARGET_Q = "greylist-max-q"
OLD_FLAG_MAX_TARGET_R = "greylist-max-r"
OLD_FLAGS_TO_NEW = {
OLD_FLAG_SDK: FLAG_SDK,
OLD_FLAG_UNSUPPORTED: FLAG_UNSUPPORTED,
OLD_FLAG_BLOCKED: FLAG_BLOCKED,
OLD_FLAG_MAX_TARGET_O: FLAG_MAX_TARGET_O,
OLD_FLAG_MAX_TARGET_P: FLAG_MAX_TARGET_P,
OLD_FLAG_MAX_TARGET_Q: FLAG_MAX_TARGET_Q,
OLD_FLAG_MAX_TARGET_R: FLAG_MAX_TARGET_R,
}
NEW_FLAGS_TO_OLD = dict(zip(OLD_FLAGS_TO_NEW.values(), OLD_FLAGS_TO_NEW.keys()))
# List of all known flags. # List of all known flags.
FLAGS_API_LIST = [ FLAGS_API_LIST = [
FLAG_WHITELIST, FLAG_SDK,
FLAG_GREYLIST, FLAG_UNSUPPORTED,
FLAG_BLACKLIST, FLAG_BLOCKED,
FLAG_GREYLIST_MAX_O, FLAG_MAX_TARGET_O,
FLAG_GREYLIST_MAX_P, FLAG_MAX_TARGET_P,
FLAG_GREYLIST_MAX_Q, FLAG_MAX_TARGET_Q,
FLAG_GREYLIST_MAX_R, FLAG_MAX_TARGET_R,
] ]
ALL_FLAGS = FLAGS_API_LIST + [ ALL_FLAGS = FLAGS_API_LIST + [
FLAG_CORE_PLATFORM_API, FLAG_CORE_PLATFORM_API,
@@ -58,7 +76,7 @@ ALL_FLAGS_SET = set(ALL_FLAGS)
# Suffix used in command line args to express that only known and # Suffix used in command line args to express that only known and
# otherwise unassigned entries should be assign the given flag. # otherwise unassigned entries should be assign the given flag.
# For example, the P dark greylist is checked in as it was in P, # For example, the max-target-P list is checked in as it was in P,
# but signatures have changes since then. The flag instructs this # but signatures have changes since then. The flag instructs this
# script to skip any entries which do not exist any more. # script to skip any entries which do not exist any more.
FLAG_IGNORE_CONFLICTS_SUFFIX = "-ignore-conflicts" FLAG_IGNORE_CONFLICTS_SUFFIX = "-ignore-conflicts"
@@ -87,6 +105,7 @@ SERIALIZATION_REGEX = re.compile(r'.*->(' + '|'.join(SERIALIZATION_PATTERNS) + r
HAS_NO_API_LIST_ASSIGNED = lambda api, flags: not FLAGS_API_LIST_SET.intersection(flags) HAS_NO_API_LIST_ASSIGNED = lambda api, flags: not FLAGS_API_LIST_SET.intersection(flags)
IS_SERIALIZATION = lambda api, flags: SERIALIZATION_REGEX.match(api) IS_SERIALIZATION = lambda api, flags: SERIALIZATION_REGEX.match(api)
def get_args(): def get_args():
"""Parses command line arguments. """Parses command line arguments.
@@ -113,6 +132,7 @@ def get_args():
return parser.parse_args() return parser.parse_args()
def read_lines(filename): def read_lines(filename):
"""Reads entire file and return it as a list of lines. """Reads entire file and return it as a list of lines.
@@ -130,8 +150,9 @@ def read_lines(filename):
lines = map(lambda line: line.strip(), lines) lines = map(lambda line: line.strip(), lines)
return set(lines) return set(lines)
def write_lines(filename, lines): def write_lines(filename, lines):
"""Writes list of lines into a file, overwriting the file it it exists. """Writes list of lines into a file, overwriting the file if it exists.
Args: Args:
filename (string): Path to the file to be writting into. filename (string): Path to the file to be writting into.
@@ -141,6 +162,7 @@ def write_lines(filename, lines):
with open(filename, 'w') as f: with open(filename, 'w') as f:
f.writelines(lines) f.writelines(lines)
def extract_package(signature): def extract_package(signature):
"""Extracts the package from a signature. """Extracts the package from a signature.
@@ -159,6 +181,7 @@ def extract_package(signature):
package_name = full_class_name.rpartition("/")[0] package_name = full_class_name.rpartition("/")[0]
return package_name.replace('/', '.') return package_name.replace('/', '.')
class FlagsDict: class FlagsDict:
def __init__(self): def __init__(self):
self._dict_keyset = set() self._dict_keyset = set()
@@ -182,6 +205,36 @@ class FlagsDict:
"Please visit go/hiddenapi for more information.").format( "Please visit go/hiddenapi for more information.").format(
source, "\n".join(flags_subset - ALL_FLAGS_SET)) source, "\n".join(flags_subset - ALL_FLAGS_SET))
def convert_to_new_flag(self, flag):
"""Converts old flag to a new variant.
Flags that are considered old are replaced with new versions.
Otherwise, it is a no-op.
Args:
flag: a string, representing SDK flag.
Returns:
A string. Result of conversion.
"""
return OLD_FLAGS_TO_NEW.get(flag, flag)
def convert_to_old_flag(self, flag):
"""Converts a new flag to a old variant.
No-op if there is no suitable old flag.
Only used to support backwards compatibility.
Args:
flag: a string, representing SDK flag.
Returns:
A string. Result of conversion.
"""
return NEW_FLAGS_TO_OLD.get(flag, flag)
def filter_apis(self, filter_fn): def filter_apis(self, filter_fn):
"""Returns APIs which match a given predicate. """Returns APIs which match a given predicate.
@@ -212,10 +265,16 @@ class FlagsDict:
def generate_csv(self): def generate_csv(self):
"""Constructs CSV entries from a dictionary. """Constructs CSV entries from a dictionary.
Old versions of flags are used to generate the file.
Returns: Returns:
List of lines comprising a CSV file. See "parse_and_merge_csv" for format description. List of lines comprising a CSV file. See "parse_and_merge_csv" for format description.
""" """
return sorted(map(lambda api: ",".join([api] + sorted(self._dict[api])), self._dict)) lines = []
for api in self._dict:
flags = sorted([self.convert_to_old_flag(flag) for flag in self._dict[api]])
lines.append(",".join([api] + flags))
return sorted(lines)
def parse_and_merge_csv(self, csv_lines, source = "<unknown>"): def parse_and_merge_csv(self, csv_lines, source = "<unknown>"):
"""Parses CSV entries and merges them into a given dictionary. """Parses CSV entries and merges them into a given dictionary.
@@ -237,17 +296,16 @@ class FlagsDict:
self._dict_keyset.update([ csv[0] for csv in csv_values ]) self._dict_keyset.update([ csv[0] for csv in csv_values ])
# Check that all flags are known. # Check that all flags are known.
csv_flags = set(functools.reduce( csv_flags = set()
lambda x, y: set(x).union(y), for csv in csv_values:
[ csv[1:] for csv in csv_values ], csv_flags.update([self.convert_to_new_flag(flag) for flag in csv[1:]])
[]))
self._check_flags_set(csv_flags, source) self._check_flags_set(csv_flags, source)
# Iterate over all CSV lines, find entry in dict and append flags to it. # Iterate over all CSV lines, find entry in dict and append flags to it.
for csv in csv_values: for csv in csv_values:
flags = csv[1:] flags = [self.convert_to_new_flag(flag) for flag in csv[1:]]
if (FLAG_PUBLIC_API in flags) or (FLAG_SYSTEM_API in flags): if (FLAG_PUBLIC_API in flags) or (FLAG_SYSTEM_API in flags):
flags.append(FLAG_WHITELIST) flags.append(FLAG_SDK)
self._dict[csv[0]].update(flags) self._dict[csv[0]].update(flags)
def assign_flag(self, flag, apis, source="<unknown>"): def assign_flag(self, flag, apis, source="<unknown>"):
@@ -271,6 +329,7 @@ class FlagsDict:
for api in apis: for api in apis:
self._dict[api].add(flag) self._dict[api].add(flag)
def main(argv): def main(argv):
# Parse arguments. # Parse arguments.
args = vars(get_args()) args = vars(get_args())
@@ -287,8 +346,8 @@ def main(argv):
flags.parse_and_merge_csv(read_lines(filename), filename) flags.parse_and_merge_csv(read_lines(filename), filename)
# Combine inputs which do not require any particular order. # Combine inputs which do not require any particular order.
# (1) Assign serialization API to whitelist. # (1) Assign serialization API to SDK.
flags.assign_flag(FLAG_WHITELIST, flags.filter_apis(IS_SERIALIZATION)) flags.assign_flag(FLAG_SDK, flags.filter_apis(IS_SERIALIZATION))
# (2) Merge text files with a known flag into the dictionary. # (2) Merge text files with a known flag into the dictionary.
for flag in ALL_FLAGS: for flag in ALL_FLAGS:
@@ -314,8 +373,8 @@ def main(argv):
valid_entries = flags.filter_apis(should_add_signature_to_list) valid_entries = flags.filter_apis(should_add_signature_to_list)
flags.assign_flag(flag, valid_entries) flags.assign_flag(flag, valid_entries)
# Assign all remaining entries to the blacklist. # Mark all remaining entries as blocked.
flags.assign_flag(FLAG_BLACKLIST, flags.filter_apis(HAS_NO_API_LIST_ASSIGNED)) flags.assign_flag(FLAG_BLOCKED, flags.filter_apis(HAS_NO_API_LIST_ASSIGNED))
# Write output. # Write output.
write_lines(args["output"], flags.generate_csv()) write_lines(args["output"], flags.generate_csv())

View File

@@ -23,7 +23,7 @@ class TestHiddenapiListGeneration(unittest.TestCase):
# Initialize flags so that A and B are put on the whitelist and # Initialize flags so that A and B are put on the whitelist and
# C, D, E are left unassigned. Try filtering for the unassigned ones. # C, D, E are left unassigned. Try filtering for the unassigned ones.
flags = FlagsDict() flags = FlagsDict()
flags.parse_and_merge_csv(['A,' + FLAG_WHITELIST, 'B,' + FLAG_WHITELIST, flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B,' + FLAG_SDK,
'C', 'D', 'E']) 'C', 'D', 'E'])
filter_set = flags.filter_apis(lambda api, flags: not flags) filter_set = flags.filter_apis(lambda api, flags: not flags)
self.assertTrue(isinstance(filter_set, set)) self.assertTrue(isinstance(filter_set, set))
@@ -32,10 +32,10 @@ class TestHiddenapiListGeneration(unittest.TestCase):
def test_get_valid_subset_of_unassigned_keys(self): def test_get_valid_subset_of_unassigned_keys(self):
# Create flags where only A is unassigned. # Create flags where only A is unassigned.
flags = FlagsDict() flags = FlagsDict()
flags.parse_and_merge_csv(['A,' + FLAG_WHITELIST, 'B', 'C']) flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B', 'C'])
flags.assign_flag(FLAG_GREYLIST, set(['C'])) flags.assign_flag(FLAG_UNSUPPORTED, set(['C']))
self.assertEqual(flags.generate_csv(), self.assertEqual(flags.generate_csv(),
[ 'A,' + FLAG_WHITELIST, 'B', 'C,' + FLAG_GREYLIST ]) [ 'A,' + OLD_FLAG_SDK, 'B', 'C,' + OLD_FLAG_UNSUPPORTED ])
# Check three things: # Check three things:
# (1) B is selected as valid unassigned # (1) B is selected as valid unassigned
@@ -50,20 +50,21 @@ class TestHiddenapiListGeneration(unittest.TestCase):
# Test empty CSV entry. # Test empty CSV entry.
self.assertEqual(flags.generate_csv(), []) self.assertEqual(flags.generate_csv(), [])
# Test new additions. # Test new additions. CSV generator produces values with old flags
# to be backwards compatible.
flags.parse_and_merge_csv([ flags.parse_and_merge_csv([
'A,' + FLAG_GREYLIST, 'A,' + FLAG_UNSUPPORTED,
'B,' + FLAG_BLACKLIST + ',' + FLAG_GREYLIST_MAX_O, 'B,' + FLAG_BLOCKED + ',' + FLAG_MAX_TARGET_O,
'C,' + FLAG_SYSTEM_API + ',' + FLAG_WHITELIST, 'C,' + FLAG_SDK + ',' + FLAG_SYSTEM_API,
'D,' + FLAG_GREYLIST+ ',' + FLAG_TEST_API, 'D,' + FLAG_UNSUPPORTED + ',' + FLAG_TEST_API,
'E,' + FLAG_BLACKLIST+ ',' + FLAG_TEST_API, 'E,' + FLAG_BLOCKED + ',' + FLAG_TEST_API,
]) ])
self.assertEqual(flags.generate_csv(), [ self.assertEqual(flags.generate_csv(), [
'A,' + FLAG_GREYLIST, 'A,' + OLD_FLAG_UNSUPPORTED,
'B,' + FLAG_BLACKLIST + "," + FLAG_GREYLIST_MAX_O, 'B,' + OLD_FLAG_BLOCKED + "," + OLD_FLAG_MAX_TARGET_O,
'C,' + FLAG_SYSTEM_API + ',' + FLAG_WHITELIST, 'C,' + FLAG_SYSTEM_API + ',' + OLD_FLAG_SDK,
'D,' + FLAG_GREYLIST+ ',' + FLAG_TEST_API, 'D,' + OLD_FLAG_UNSUPPORTED + ',' + FLAG_TEST_API,
'E,' + FLAG_BLACKLIST+ ',' + FLAG_TEST_API, 'E,' + OLD_FLAG_BLOCKED + ',' + FLAG_TEST_API,
]) ])
# Test unknown flag. # Test unknown flag.
@@ -72,16 +73,16 @@ class TestHiddenapiListGeneration(unittest.TestCase):
def test_assign_flag(self): def test_assign_flag(self):
flags = FlagsDict() flags = FlagsDict()
flags.parse_and_merge_csv(['A,' + FLAG_WHITELIST, 'B']) flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B'])
# Test new additions. # Test new additions.
flags.assign_flag(FLAG_GREYLIST, set([ 'A', 'B' ])) flags.assign_flag(FLAG_UNSUPPORTED, set([ 'A', 'B' ]))
self.assertEqual(flags.generate_csv(), self.assertEqual(flags.generate_csv(),
[ 'A,' + FLAG_GREYLIST + "," + FLAG_WHITELIST, 'B,' + FLAG_GREYLIST ]) [ 'A,' + OLD_FLAG_UNSUPPORTED + "," + OLD_FLAG_SDK, 'B,' + OLD_FLAG_UNSUPPORTED ])
# Test invalid API signature. # Test invalid API signature.
with self.assertRaises(AssertionError): with self.assertRaises(AssertionError):
flags.assign_flag(FLAG_WHITELIST, set([ 'C' ])) flags.assign_flag(FLAG_SDK, set([ 'C' ]))
# Test invalid flag. # Test invalid flag.
with self.assertRaises(AssertionError): with self.assertRaises(AssertionError):