From 5a082f9a3310a425115061578ed8955ff342ef56 Mon Sep 17 00:00:00 2001 From: William Loh Date: Tue, 17 May 2022 20:21:50 +0000 Subject: [PATCH] Propagate max_sdk_version to manifest_fixer If max_sdk_version is included in Android.bp that value will now be propagated to manifest_fixer.py. This value will then be used to override any maxSdkVersion attribute set on permission or uses-permission tags in the android manifest if maxSdkVersion="-1". Bug: 223902327 Test: add max_sdk_version to Android.bp for test app Test: create permission in test app manifest with maxSdkVersion="-1" Test: run test to check maxSdkVersion=max_sdk_version Change-Id: Ic533ef2a41b9ecc9ee68c69399026df47ee945b7 --- android/sdk_version.go | 3 ++ java/aar.go | 4 ++ java/android_manifest.go | 6 +++ java/base.go | 9 +++++ java/droiddoc.go | 4 ++ java/java.go | 11 ++++++ java/rro.go | 4 ++ scripts/manifest_fixer.py | 23 +++++++++++ scripts/manifest_fixer_test.py | 72 ++++++++++++++++++++++++++++++++++ 9 files changed, 136 insertions(+) diff --git a/android/sdk_version.go b/android/sdk_version.go index 2004c9290..c188c4808 100644 --- a/android/sdk_version.go +++ b/android/sdk_version.go @@ -28,6 +28,9 @@ type SdkContext interface { // MinSdkVersion returns SdkSpec that corresponds to the min_sdk_version property of the current module, // or from sdk_version if it is not set. MinSdkVersion(ctx EarlyModuleContext) SdkSpec + // ReplaceMaxSdkVersionPlaceholder returns SdkSpec to replace the maxSdkVersion property of permission and + // uses-permission tags if it is set. + ReplaceMaxSdkVersionPlaceholder(ctx EarlyModuleContext) SdkSpec // TargetSdkVersion returns the SdkSpec that corresponds to the target_sdk_version property of the current module, // or from sdk_version if it is not set. TargetSdkVersion(ctx EarlyModuleContext) SdkSpec diff --git a/java/aar.go b/java/aar.go index 00ff7e774..cf84309f4 100644 --- a/java/aar.go +++ b/java/aar.go @@ -678,6 +678,10 @@ func (a *AARImport) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpe return a.SdkVersion(ctx) } +func (a *AARImport) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec { + return android.SdkSpecFrom(ctx, "") +} + func (a *AARImport) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return a.SdkVersion(ctx) } diff --git a/java/android_manifest.go b/java/android_manifest.go index a297b2c10..c61823d06 100644 --- a/java/android_manifest.go +++ b/java/android_manifest.go @@ -136,6 +136,11 @@ func ManifestFixer(ctx android.ModuleContext, manifest android.Path, ctx.ModuleErrorf("invalid minSdkVersion: %s", err) } + replaceMaxSdkVersionPlaceholder, err := params.SdkContext.ReplaceMaxSdkVersionPlaceholder(ctx).EffectiveVersion(ctx) + if err != nil { + ctx.ModuleErrorf("invalid ReplaceMaxSdkVersionPlaceholder: %s", err) + } + if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" { minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String()) deps = append(deps, ApiFingerprintPath(ctx)) @@ -145,6 +150,7 @@ func ManifestFixer(ctx android.ModuleContext, manifest android.Path, ctx.ModuleErrorf("invalid minSdkVersion: %s", err) } args = append(args, "--minSdkVersion ", minSdkVersion) + args = append(args, "--replaceMaxSdkVersionPlaceholder ", strconv.Itoa(replaceMaxSdkVersionPlaceholder.FinalOrFutureInt())) args = append(args, "--raise-min-sdk-version") } diff --git a/java/base.go b/java/base.go index 0900daaae..a249ed993 100644 --- a/java/base.go +++ b/java/base.go @@ -204,6 +204,10 @@ type DeviceProperties struct { // Defaults to empty string "". See sdk_version for possible values. Max_sdk_version *string + // if not blank, set the maxSdkVersion properties of permission and uses-permission tags. + // Defaults to empty string "". See sdk_version for possible values. + Replace_max_sdk_version_placeholder *string + // if not blank, set the targetSdkVersion in the AndroidManifest.xml. // Defaults to sdk_version if not set. See sdk_version for possible values. Target_sdk_version *string @@ -649,6 +653,11 @@ func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return android.SdkSpecFrom(ctx, maxSdkVersion) } +func (j *Module) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec { + replaceMaxSdkVersionPlaceholder := proptools.StringDefault(j.deviceProperties.Replace_max_sdk_version_placeholder, "") + return android.SdkSpecFrom(ctx, replaceMaxSdkVersionPlaceholder) +} + func (j *Module) MinSdkVersionString() string { return j.minSdkVersion.Raw } diff --git a/java/droiddoc.go b/java/droiddoc.go index 023d61912..96639220a 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -256,6 +256,10 @@ func (j *Javadoc) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec return j.SdkVersion(ctx) } +func (j *Javadoc) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec { + return j.SdkVersion(ctx) +} + func (j *Javadoc) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return j.SdkVersion(ctx) } diff --git a/java/java.go b/java/java.go index 0dfb968e9..7d40a7e27 100644 --- a/java/java.go +++ b/java/java.go @@ -1327,6 +1327,10 @@ type ImportProperties struct { // specified. Min_sdk_version *string + // The max sdk version placeholder used to replace maxSdkVersion attributes on permission + // and uses-permission tags in manifest_fixer. + Replace_max_sdk_version_placeholder *string + Installable *bool // If not empty, classes are restricted to the specified packages and their sub-packages. @@ -1406,6 +1410,13 @@ func (j *Import) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return j.SdkVersion(ctx) } +func (j *Import) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec { + if j.properties.Replace_max_sdk_version_placeholder != nil { + return android.SdkSpecFrom(ctx, *j.properties.Replace_max_sdk_version_placeholder) + } + return android.SdkSpecFrom(ctx, "") +} + func (j *Import) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return j.SdkVersion(ctx) } diff --git a/java/rro.go b/java/rro.go index be84afffc..7952c2cc4 100644 --- a/java/rro.go +++ b/java/rro.go @@ -173,6 +173,10 @@ func (r *RuntimeResourceOverlay) MinSdkVersion(ctx android.EarlyModuleContext) a return r.SdkVersion(ctx) } +func (r *RuntimeResourceOverlay) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec { + return android.SdkSpecFrom(ctx, "") +} + func (r *RuntimeResourceOverlay) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return r.SdkVersion(ctx) } diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py index 2d3103b43..2da29ee91 100755 --- a/scripts/manifest_fixer.py +++ b/scripts/manifest_fixer.py @@ -39,6 +39,8 @@ def parse_args(): parser = argparse.ArgumentParser() parser.add_argument('--minSdkVersion', default='', dest='min_sdk_version', help='specify minSdkVersion used by the build system') + parser.add_argument('--replaceMaxSdkVersionPlaceholder', default='', dest='max_sdk_version', + help='specify maxSdkVersion used by the build system') parser.add_argument('--targetSdkVersion', default='', dest='target_sdk_version', help='specify targetSdkVersion used by the build system') parser.add_argument('--raise-min-sdk-version', dest='raise_min_sdk_version', action='store_true', @@ -342,6 +344,24 @@ def set_test_only_flag_to_true(doc): attr.value = 'true' application.setAttributeNode(attr) +def set_max_sdk_version(doc, max_sdk_version): + """Replace the maxSdkVersion attribute value for permission and + uses-permission tags if the value was originally set to 'current'. + Used for cts test cases where the maxSdkVersion should equal to + Build.SDK_INT. + + Args: + doc: The XML document. May be modified by this function. + max_sdk_version: The requested maxSdkVersion attribute. + """ + manifest = parse_manifest(doc) + for tag in ['permission', 'uses-permission']: + children = get_children_with_tag(manifest, tag) + for child in children: + max_attr = child.getAttributeNodeNS(android_ns, 'maxSdkVersion') + if max_attr and max_attr.value == 'current': + max_attr.value = max_sdk_version + def main(): """Program entry point.""" try: @@ -354,6 +374,9 @@ def main(): if args.raise_min_sdk_version: raise_min_sdk_version(doc, args.min_sdk_version, args.target_sdk_version, args.library) + if args.max_sdk_version: + set_max_sdk_version(doc, args.max_sdk_version) + if args.uses_libraries: add_uses_libraries(doc, args.uses_libraries, True) diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py index 199b279cd..dad104a54 100755 --- a/scripts/manifest_fixer_test.py +++ b/scripts/manifest_fixer_test.py @@ -571,5 +571,77 @@ class AddTestOnlyApplicationTest(unittest.TestCase): output = self.run_test(manifest_input) self.assert_xml_equal(output, manifest_input) + +class SetMaxSdkVersionTest(unittest.TestCase): + """Unit tests for set_max_sdk_version function.""" + + def assert_xml_equal(self, output, expected): + self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected)) + + def run_test(self, input_manifest, max_sdk_version): + doc = minidom.parseString(input_manifest) + manifest_fixer.set_max_sdk_version(doc, max_sdk_version) + output = io.StringIO() + manifest_fixer.write_xml(output, doc) + return output.getvalue() + + manifest_tmpl = ( + '\n' + '\n' + '%s' + '\n') + + def permission(self, max=None): + if max is None: + return ' ' + return ' \n' % max + + def uses_permission(self, max=None): + if max is None: + return ' ' + return ' \n' % max + + def test_permission_no_max_sdk_version(self): + """Tests if permission has no maxSdkVersion attribute""" + manifest_input = self.manifest_tmpl % self.permission() + expected = self.manifest_tmpl % self.permission() + output = self.run_test(manifest_input, '9000') + self.assert_xml_equal(output, expected) + + def test_permission_max_sdk_version_changed(self): + """Tests if permission maxSdkVersion attribute is set to current""" + manifest_input = self.manifest_tmpl % self.permission('current') + expected = self.manifest_tmpl % self.permission(9000) + output = self.run_test(manifest_input, '9000') + self.assert_xml_equal(output, expected) + + def test_permission_max_sdk_version_not_changed(self): + """Tests if permission maxSdkVersion attribute is not set to current""" + manifest_input = self.manifest_tmpl % self.permission(30) + expected = self.manifest_tmpl % self.permission(30) + output = self.run_test(manifest_input, '9000') + self.assert_xml_equal(output, expected) + + def test_uses_permission_no_max_sdk_version(self): + """Tests if uses-permission has no maxSdkVersion attribute""" + manifest_input = self.manifest_tmpl % self.uses_permission() + expected = self.manifest_tmpl % self.uses_permission() + output = self.run_test(manifest_input, '9000') + self.assert_xml_equal(output, expected) + + def test_uses_permission_max_sdk_version_changed(self): + """Tests if uses-permission maxSdkVersion attribute is set to current""" + manifest_input = self.manifest_tmpl % self.uses_permission('current') + expected = self.manifest_tmpl % self.uses_permission(9000) + output = self.run_test(manifest_input, '9000') + self.assert_xml_equal(output, expected) + + def test_uses_permission_max_sdk_version_not_changed(self): + """Tests if uses-permission maxSdkVersion attribute is not set to current""" + manifest_input = self.manifest_tmpl % self.uses_permission(30) + expected = self.manifest_tmpl % self.uses_permission(30) + output = self.run_test(manifest_input, '9000') + self.assert_xml_equal(output, expected) + if __name__ == '__main__': unittest.main(verbosity=2)