From 20e0fefc391fc97495059efeb0460cc22ec6e8d3 Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Fri, 1 Mar 2024 13:45:48 -1000 Subject: [PATCH 1/4] [manifest-attribute-codegen] Automatically generate manifest attributes from Android SDK data. --- .../Extensions/StringExtensions.cs | 120 +++++++ .../Models/AttributeDefinition.cs | 50 +++ .../Models/ElementDefinition.cs | 50 +++ .../Models/EnumDefinition.cs | 15 + .../Models/ManifestDefinition.cs | 87 +++++ .../Models/MetadataSource.cs | 148 +++++++++ .../manifest-attribute-codegen/Program.cs | 95 ++++++ .../SourceWriters/AttributeDataClass.cs | 89 ++++++ .../SourceWriters/AttributeUsageAttr.cs | 20 ++ .../SourceWriters/ObsoleteAttr.cs | 18 ++ .../SourceWriters/SerializableAttr.cs | 11 + .../manifest-attribute-codegen.cs | 224 ------------- .../manifest-attribute-codegen.csproj | 38 +++ .../manifest-attribute-codegen/metadata.xml | 296 ++++++++++++++++++ .../IntentFilterAttribute.Partial.cs | 36 +++ .../Android.App/IntentFilterAttribute.cs | 78 ++--- .../Android.App/MetaDataAttribute.Partial.cs | 11 + .../Android.App/MetaDataAttribute.cs | 33 +- .../Android.App/PermissionAttribute.cs | 58 ++-- .../Android.App/PermissionGroupAttribute.cs | 46 +-- .../Android.App/PermissionTreeAttribute.cs | 43 +-- .../Android.App/UsesConfigurationAttribute.cs | 44 +-- .../UsesFeatureAttribute.Partial.cs | 11 + .../Android.App/UsesFeatureAttribute.cs | 51 +-- .../UsesLibraryAttribute.Partial.cs | 16 + .../Android.App/UsesLibraryAttribute.cs | 42 ++- .../GrantUriPermissionAttribute.cs | 36 ++- src/Mono.Android/Mono.Android.csproj | 4 + .../Xamarin.Android.Build.Tasks.csproj | 12 + .../Android.App/ActivityAttribute.Partial.cs | 13 + .../Android.App/ActivityAttribute.cs | 258 ++++++++------- .../Android.App/ApplicationAttribute.cs | 182 +++++------ .../Android.App/InstrumentationAttribute.cs | 60 ++-- .../Android.App/LayoutAttribute.cs | 44 ++- .../Android.App/ServiceAttribute.cs | 76 ++--- .../BroadcastReceiverAttribute.cs | 63 ++-- .../ContentProviderAttribute.Partial.cs | 15 + .../ContentProviderAttribute.cs | 86 ++--- ...n.Android.NamingCustomAttributes.projitems | 2 + 39 files changed, 1785 insertions(+), 796 deletions(-) create mode 100644 build-tools/manifest-attribute-codegen/Extensions/StringExtensions.cs create mode 100644 build-tools/manifest-attribute-codegen/Models/AttributeDefinition.cs create mode 100644 build-tools/manifest-attribute-codegen/Models/ElementDefinition.cs create mode 100644 build-tools/manifest-attribute-codegen/Models/EnumDefinition.cs create mode 100644 build-tools/manifest-attribute-codegen/Models/ManifestDefinition.cs create mode 100644 build-tools/manifest-attribute-codegen/Models/MetadataSource.cs create mode 100644 build-tools/manifest-attribute-codegen/Program.cs create mode 100644 build-tools/manifest-attribute-codegen/SourceWriters/AttributeDataClass.cs create mode 100644 build-tools/manifest-attribute-codegen/SourceWriters/AttributeUsageAttr.cs create mode 100644 build-tools/manifest-attribute-codegen/SourceWriters/ObsoleteAttr.cs create mode 100644 build-tools/manifest-attribute-codegen/SourceWriters/SerializableAttr.cs delete mode 100644 build-tools/manifest-attribute-codegen/manifest-attribute-codegen.cs create mode 100644 build-tools/manifest-attribute-codegen/manifest-attribute-codegen.csproj create mode 100644 build-tools/manifest-attribute-codegen/metadata.xml create mode 100644 src/Mono.Android/Android.App/IntentFilterAttribute.Partial.cs create mode 100644 src/Mono.Android/Android.App/MetaDataAttribute.Partial.cs create mode 100644 src/Mono.Android/Android.App/UsesFeatureAttribute.Partial.cs create mode 100644 src/Mono.Android/Android.App/UsesLibraryAttribute.Partial.cs create mode 100644 src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.Partial.cs create mode 100644 src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.Partial.cs diff --git a/build-tools/manifest-attribute-codegen/Extensions/StringExtensions.cs b/build-tools/manifest-attribute-codegen/Extensions/StringExtensions.cs new file mode 100644 index 00000000000..254a5fc4f07 --- /dev/null +++ b/build-tools/manifest-attribute-codegen/Extensions/StringExtensions.cs @@ -0,0 +1,120 @@ +using System.Text; +using System.Xml.Linq; +using Xamarin.SourceWriter; + +namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; + +static class StringExtensions +{ + static StringExtensions () + { + // micro unit testing, am so clever! + if (Hyphenate ("AndSoOn") != "and-so-on") + throw new InvalidOperationException ("Am so buggy 1 " + Hyphenate ("AndSoOn")); + if (Hyphenate ("aBigProblem") != "a-big-problem") + throw new InvalidOperationException ("Am so buggy 2"); + if (Hyphenate ("my-two-cents") != "my-two-cents") + throw new InvalidOperationException ("Am so buggy 3"); + } + + public static string Hyphenate (this string s) + { + var sb = new StringBuilder (s.Length * 2); + for (int i = 0; i < s.Length; i++) { + if (char.IsUpper (s [i])) { + if (i > 0) + sb.Append ('-'); + sb.Append (char.ToLowerInvariant (s [i])); + } else + sb.Append (s [i]); + } + return sb.ToString (); + } + + const string prefix = "AndroidManifest"; + + public static string ToActualName (this string s) + { + s = s.IndexOf ('.') < 0 ? s : s.Substring (s.LastIndexOf ('.') + 1); + + var ret = (s.StartsWith (prefix, StringComparison.Ordinal) ? s.Substring (prefix.Length) : s).Hyphenate (); + return ret.Length == 0 ? "manifest" : ret; + } + + public static bool? GetAsBoolOrNull (this XElement element, string attribute) + { + var value = element.Attribute (attribute)?.Value; + + if (value is null) + return null; + + if (bool.TryParse (value, out var ret)) + return ret; + + return null; + } + + public static bool GetAttributeBoolOrDefault (this XElement element, string attribute, bool defaultValue) + { + var value = element.Attribute (attribute)?.Value; + + if (value is null) + return defaultValue; + + if (bool.TryParse (value, out var ret)) + return ret; + + return defaultValue; + } + + public static string GetRequiredAttributeString (this XElement element, string attribute) + { + var value = element.Attribute (attribute)?.Value; + + if (value is null) + throw new InvalidDataException ($"Missing '{attribute}' attribute."); + + return value; + } + + public static string GetAttributeStringOrEmpty (this XElement element, string attribute) + => element.Attribute (attribute)?.Value ?? string.Empty; + + public static string Unhyphenate (this string s) + { + if (s.IndexOf ('-') < 0) + return s; + + var sb = new StringBuilder (); + + for (var i = 0; i < s.Length; i++) { + if (s [i] == '-') { + sb.Append (char.ToUpper (s [i + 1])); + i++; + } else { + sb.Append (s [i]); + } + } + + return sb.ToString (); + } + + public static string Capitalize (this string s) + { + return char.ToUpper (s [0]) + s.Substring (1); + } + + public static void WriteAutoGeneratedHeader (this CodeWriter sw) + { + sw.WriteLine ("//------------------------------------------------------------------------------"); + sw.WriteLine ("// "); + sw.WriteLine ("// This code was generated by 'manifest-attribute-codegen'."); + sw.WriteLine ("//"); + sw.WriteLine ("// Changes to this file may cause incorrect behavior and will be lost if"); + sw.WriteLine ("// the code is regenerated."); + sw.WriteLine ("// "); + sw.WriteLine ("//------------------------------------------------------------------------------"); + sw.WriteLine (); + sw.WriteLine ("#nullable enable"); // Roslyn turns off NRT for generated files by default, re-enable it + } +} diff --git a/build-tools/manifest-attribute-codegen/Models/AttributeDefinition.cs b/build-tools/manifest-attribute-codegen/Models/AttributeDefinition.cs new file mode 100644 index 00000000000..3e3183021a3 --- /dev/null +++ b/build-tools/manifest-attribute-codegen/Models/AttributeDefinition.cs @@ -0,0 +1,50 @@ +using System.Xml.Linq; +using Xamarin.SourceWriter; + +namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; + +class AttributeDefinition +{ + public string ApiLevel { get; } + public string Name { get; } + public string Format { get; } + public List Enums { get; } = new List (); + + public AttributeDefinition (string apiLevel, string name, string format) + { + ApiLevel = apiLevel; + Name = name; + Format = format; + } + + public static AttributeDefinition FromElement (string api, XElement e) + { + var name = e.GetAttributeStringOrEmpty ("name"); + var format = e.GetAttributeStringOrEmpty ("format"); + + var def = new AttributeDefinition (api, name, format); + + var enums = e.Elements ("enum") + .Select (n => new EnumDefinition (api, n.GetAttributeStringOrEmpty ("name"), n.GetAttributeStringOrEmpty ("value"))); + + def.Enums.AddRange (enums); + + return def; + } + + public void WriteXml (TextWriter w) + { + var format = Format.HasValue () ? $" format='{Format}'" : string.Empty; + var api_level = int.TryParse (ApiLevel, out var level) && level <= 10 ? string.Empty : $" api-level='{ApiLevel}'"; + + w.Write ($" 0) { + w.WriteLine (">"); + foreach (var e in Enums) + w.WriteLine ($" "); + w.WriteLine (" "); + } else + w.WriteLine (" />"); + } +} diff --git a/build-tools/manifest-attribute-codegen/Models/ElementDefinition.cs b/build-tools/manifest-attribute-codegen/Models/ElementDefinition.cs new file mode 100644 index 00000000000..76bdb26c00e --- /dev/null +++ b/build-tools/manifest-attribute-codegen/Models/ElementDefinition.cs @@ -0,0 +1,50 @@ +using System.Xml.Linq; + +namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; + +class ElementDefinition +{ + static readonly char [] sep = [' ']; + + public string ApiLevel { get; } + public string Name { get; } + public string[]? Parents { get;} + public List Attributes { get; } = new List (); + + public string ActualElementName => Name.ToActualName (); + + public ElementDefinition (string apiLevel, string name, string []? parents) + { + ApiLevel = apiLevel; + Name = name; + Parents = parents; + } + + public static ElementDefinition FromElement (string api, XElement e) + { + var name = e.GetAttributeStringOrEmpty ("name"); + var parents = e.Attribute ("parent")?.Value?.Split (sep, StringSplitOptions.RemoveEmptyEntries); + var def = new ElementDefinition (api, name, parents); + + var attrs = e.Elements ("attr") + .Select (a => AttributeDefinition.FromElement (api, a)); + + def.Attributes.AddRange (attrs); + + return def; + } + + public void WriteXml (TextWriter w) + { + w.WriteLine ($" "); + + if (Parents?.Any () == true) + foreach (var p in Parents) + w.WriteLine ($" {p.ToActualName ()}"); + + foreach (var a in Attributes) + a.WriteXml (w); + + w.WriteLine (" "); + } +} diff --git a/build-tools/manifest-attribute-codegen/Models/EnumDefinition.cs b/build-tools/manifest-attribute-codegen/Models/EnumDefinition.cs new file mode 100644 index 00000000000..e3761ed28f6 --- /dev/null +++ b/build-tools/manifest-attribute-codegen/Models/EnumDefinition.cs @@ -0,0 +1,15 @@ +namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; + +class EnumDefinition +{ + public string ApiLevel { get; set; } + public string Name { get; set; } + public string Value { get; set; } + + public EnumDefinition (string apiLevel, string name, string value) + { + ApiLevel = apiLevel; + Name = name; + Value = value; + } +} diff --git a/build-tools/manifest-attribute-codegen/Models/ManifestDefinition.cs b/build-tools/manifest-attribute-codegen/Models/ManifestDefinition.cs new file mode 100644 index 00000000000..bee25c14b95 --- /dev/null +++ b/build-tools/manifest-attribute-codegen/Models/ManifestDefinition.cs @@ -0,0 +1,87 @@ +using System.Xml.Linq; + +namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; + +class ManifestDefinition +{ + public string ApiLevel { get; set; } = "0"; + public List Elements { get; } = new List (); + + // Creates a new ManifestDefinition for a single Android API from the given file path + public static ManifestDefinition FromFile (string filePath) + { + var dir_name = new FileInfo (filePath).Directory?.Parent?.Parent?.Parent?.Name; + + if (dir_name is null) + throw new InvalidOperationException ($"Could not determine API level from {filePath}"); + + var manifest = new ManifestDefinition () { + ApiLevel = dir_name.Substring (dir_name.IndexOf ('-') + 1) + }; + + var elements = XDocument.Load (filePath).Root?.Elements ("declare-styleable") + .Select (e => ElementDefinition.FromElement (manifest.ApiLevel, e)) + .ToList (); + + if (elements is not null) + manifest.Elements.AddRange (elements); + + return manifest; + } + + public static ManifestDefinition FromSdkDirectory (string sdkPath) + { + // Load all the attrs_manifest.xml files from the Android SDK + var manifests = Directory.GetDirectories (Path.Combine (sdkPath, "platforms"), "android-*") + .Select (d => Path.Combine (d, "data", "res", "values", "attrs_manifest.xml")) + .Where (File.Exists) + .Order () + .Select (FromFile) + .ToList (); + + // Merge all the manifests into a single one + var merged = new ManifestDefinition (); + + foreach (var def in manifests) { + foreach (var el in def.Elements) { + var element = merged.Elements.FirstOrDefault (_ => _.ActualElementName == el.ActualElementName); + if (element == null) + merged.Elements.Add (element = new ElementDefinition ( + el.ApiLevel, + el.Name, + (string []?) el.Parents?.Clone () + )); + foreach (var at in el.Attributes) { + var attribute = element.Attributes.FirstOrDefault (_ => _.Name == at.Name); + if (attribute == null) + element.Attributes.Add (attribute = new AttributeDefinition ( + at.ApiLevel, + at.Name, + at.Format + )); + foreach (var en in at.Enums) { + var enumeration = at.Enums.FirstOrDefault (_ => _.Name == en.Name); + if (enumeration == null) + attribute.Enums.Add (new EnumDefinition ( + en.ApiLevel, + en.Name, + en.Value + )); + } + } + } + } + + return merged; + } + + public void WriteXml (TextWriter w) + { + w.WriteLine (""); + + foreach (var e in Elements) + e.WriteXml (w); + + w.WriteLine (""); + } +} diff --git a/build-tools/manifest-attribute-codegen/Models/MetadataSource.cs b/build-tools/manifest-attribute-codegen/Models/MetadataSource.cs new file mode 100644 index 00000000000..b830d53be9f --- /dev/null +++ b/build-tools/manifest-attribute-codegen/Models/MetadataSource.cs @@ -0,0 +1,148 @@ +using System.Text; +using System.Xml.Linq; + +namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; + +class MetadataSource +{ + public Dictionary Types { get; } = new (); + public Dictionary Elements { get; } = new (); + + static readonly MetadataElement default_element = new MetadataElement ("*"); + + + public MetadataSource (string filename) + { + var xml = XElement.Load (filename); + + foreach (var element in xml.Elements ("element")) { + var path = element.Attribute ("path")?.Value ?? throw new InvalidDataException ("Missing 'path' attribute."); + + Elements.Add (path, new MetadataElement (path) { + Visible = element.GetAsBoolOrNull ("visible"), + Type = element.Attribute ("type")?.Value, + Name = element.Attribute ("name")?.Value, + Obsolete = element.Attribute ("obsolete")?.Value, + ReadOnly = element.GetAsBoolOrNull ("readonly") ?? false, + }); + } + + foreach (var element in xml.Elements ("type")) { + var el = new MetadataType (element); + Types.Add (el.Name, el); + } + } + + public MetadataElement GetMetadata (string path) + { + if (Elements.TryGetValue (path, out var element)) { + element.Consumed = true; + return element; + } + + return default_element; + } + + public void EnsureMetadataElementsConsumed () + { + var unconsumed = Elements.Values.Where (e => !e.Consumed).ToList (); + + if (unconsumed.Count == 0) + return; + + var sb = new StringBuilder (); + sb.AppendLine ("The following metadata elements were not consumed:"); + + foreach (var e in unconsumed) + sb.AppendLine ($"- {e.Path}"); + + throw new InvalidOperationException (sb.ToString ()); + } + + public void EnsureMetadataTypesConsumed () + { + var unconsumed = Types.Values.Where (t => !t.Consumed && !t.Ignore).ToList (); + + if (unconsumed.Count == 0) + return; + + var sb = new StringBuilder (); + sb.AppendLine ("The following metadata types were not consumed:"); + + foreach (var t in unconsumed) + sb.AppendLine ($"- {t.Name}"); + + throw new InvalidOperationException (sb.ToString ()); + } + + public void EnsureAllTypesAccountedFor (IEnumerable elements) + { + var missing = new List (); + + foreach (var e in elements) { + if (!Types.ContainsKey (e.ActualElementName)) + missing.Add (e.ActualElementName); + } + + if (missing.Count == 0) + return; + + var sb = new StringBuilder (); + sb.AppendLine ("The following types were not accounted for:"); + + foreach (var m in missing.Order ()) + sb.AppendLine ($"- {m}"); + + throw new InvalidOperationException (sb.ToString ()); + } +} + +class MetadataElement +{ + public string Path { get; set; } + public bool? Visible { get; set; } + public string? Type { get; set; } + public string? Name { get; set; } + public string? Obsolete { get; set; } + public bool ReadOnly { get; set; } + public bool Consumed { get; set; } + + public MetadataElement (string path) + { + Path = path; + } +} + +public class MetadataType +{ + public string Name { get; set; } + public string ManagedName { get; set; } = string.Empty; + public string Namespace { get; set; } = string.Empty; + public bool Ignore { get; set; } + public string OutputFile { get; set; } = string.Empty; + public string Usage { get; set; } = string.Empty; + public bool AllowMultiple { get; set; } + public bool IsJniNameProvider { get; set; } + public bool HasDefaultConstructor { get; set; } + public bool IsSealed { get; set; } + public bool Consumed { get; set; } + + + public MetadataType (XElement element) + { + Name = element.GetRequiredAttributeString ("name"); + Ignore = element.GetAttributeBoolOrDefault ("ignore", false); + + if (Ignore) + return; + + Namespace = element.GetRequiredAttributeString ("namespace"); + OutputFile = element.GetRequiredAttributeString ("outputFile"); + Usage = element.GetRequiredAttributeString ("usage"); + AllowMultiple = element.GetAttributeBoolOrDefault ("allowMultiple", false); + IsJniNameProvider = element.GetAttributeBoolOrDefault ("jniNameProvider", false); + HasDefaultConstructor = element.GetAttributeBoolOrDefault("defaultConstructor", true); + IsSealed = element.GetAttributeBoolOrDefault ("sealed", true); + ManagedName = element.Attribute ("managedName")?.Value ?? Name.Unhyphenate ().Capitalize () + "Attribute"; + } +} diff --git a/build-tools/manifest-attribute-codegen/Program.cs b/build-tools/manifest-attribute-codegen/Program.cs new file mode 100644 index 00000000000..1eb5be95954 --- /dev/null +++ b/build-tools/manifest-attribute-codegen/Program.cs @@ -0,0 +1,95 @@ +using Mono.Options; +using Xamarin.SourceWriter; + +namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; + +public class Program +{ + public static int Main (string [] args) + { + var show_help = false; + string? sdk_path = null; + string? base_dir = null; + string? output_manifest = null; + string? metadata_file = null; + + var options = new OptionSet { + "Usage: manifest-attribute-codegen", + "", + "Generate manifest attributes from Android SDK platforms.", + "", + "Options:", + { "sdk-path=", + "Path to Android SDK", + v => sdk_path = v }, + { "base-dir=", + "xamarin-android repository root directory", + v => base_dir = v }, + { "metadata-file=", + "metadata file used to drive the generation process", + v => metadata_file = v }, + { "output-manifest=", + "Optional file to write merged manifest output", + v => output_manifest = v }, + { "h|?|help", + "Show this help message and exit.", + v => show_help = v != null }, + }; + + try { + options.Parse (args); + } catch (Exception e) { + Console.Error.WriteLine ("manifest-attribute-codegen: {0}", e); + return 1; + } + + if (show_help) { + options.WriteOptionDescriptions (Console.Out); + return 0; + } + + sdk_path ??= Environment.GetEnvironmentVariable ("ANDROID_SDK_HOME"); + sdk_path ??= Environment.GetEnvironmentVariable ("ANDROID_SDK_PATH"); + + if (sdk_path is null) + throw new InvalidOperationException ("Pass Android SDK location as a command argument, or specify ANDROID_SDK_HOME or ANDROID_SDK_PATH environment variable"); + + if (base_dir is null) + throw new InvalidOperationException ("Pass xamarin-android repository root directory as a command argument"); + + if (metadata_file is null) + throw new InvalidOperationException ("'metadata-file' argument must be provided"); + + // Create a merged manifest from the SDK levels + var merged = ManifestDefinition.FromSdkDirectory (sdk_path); + + if (output_manifest is not null) { + if (Path.GetDirectoryName (output_manifest) is string manifest_dir) + Directory.CreateDirectory (manifest_dir); + + using var w = new StreamWriter (output_manifest); + merged.WriteXml (w); + } + + // Read metadata file + var metadata = new MetadataSource (metadata_file); + + // Generate manifest attributes C# code + foreach (var type in metadata.Types.Values.Where (t => !t.Ignore)) { + using var w = new StreamWriter (Path.Combine (base_dir, type.OutputFile)); + using var cw = new CodeWriter (w); + var element = merged.Elements.First (_ => _.ActualElementName == type.Name); + var writer = AttributeDataClass.Create (element, metadata, type); + writer.Write (cw); + } + + // Ensure everything we found in the Android SDK is accounted for. + // This forces us to handle anything new that's been added to the SDK. + // metadata.EnsureAllTypesExist (merged.Elements); + metadata.EnsureAllTypesAccountedFor (merged.Elements); + metadata.EnsureMetadataTypesConsumed (); + metadata.EnsureMetadataElementsConsumed (); + + return 0; + } +} diff --git a/build-tools/manifest-attribute-codegen/SourceWriters/AttributeDataClass.cs b/build-tools/manifest-attribute-codegen/SourceWriters/AttributeDataClass.cs new file mode 100644 index 00000000000..50374eb674b --- /dev/null +++ b/build-tools/manifest-attribute-codegen/SourceWriters/AttributeDataClass.cs @@ -0,0 +1,89 @@ +using Xamarin.SourceWriter; + +namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; + +// This is the common data class used by both Mono.Android and Xamarin.Android.Build.Tasks. +class AttributeDataClass : ClassWriter +{ + public string Namespace { get; set; } + + public AttributeDataClass (string ns) + { + Namespace = ns; + } + + public static AttributeDataClass Create (ElementDefinition attr, MetadataSource metadata, MetadataType type) + { + type.Consumed = true; + + var c = new AttributeDataClass (type.Namespace) { + Name = type.ManagedName, + IsPublic = true, + IsPartial = true, + IsSealed = type.IsSealed, + Inherits = "Attribute", + }; + + if (type.IsJniNameProvider) + c.Implements.Add ("Java.Interop.IJniNameProviderAttribute"); + + c.Attributes.Add (new SerializableAttr ()); + c.Attributes.Add (new AttributeUsageAttr (type)); + + // Add empty constructor + if (type.HasDefaultConstructor) + c.Constructors.Add (new ConstructorWriter { + Name = c.Name, + IsPublic = true, + }); + + // Add properties + foreach (var a in attr.Attributes.OrderBy (a => a.Name)) { + var attr_metadata = metadata.GetMetadata ($"{attr.ActualElementName}.{a.Name}"); + + if (attr_metadata.Visible == false) + continue; + + var p = new PropertyWriter { + Name = (attr_metadata.Name ?? a.Name).Capitalize (), + PropertyType = new TypeReferenceWriter (attr_metadata.Type ?? GetAttributeType (a)), + IsPublic = true, + HasGet = true, + HasSet = true, + IsAutoProperty = true, + AutoSetterVisibility = attr_metadata.ReadOnly ? Visibility.Private : Visibility.Public, + }; + + // Add obsolete attribute + if (attr_metadata.Obsolete is not null) + p.Attributes.Add (new ObsoleteAttr (attr_metadata.Obsolete)); + + c.Properties.Add (p); + } + + return c; + } + + static string GetAttributeType (AttributeDefinition attr) + { + return attr.Format switch { + "boolean" => "bool", + "integer" => "int", + "string" => "string?", + _ => "string?", + }; + } + + public override void Write (CodeWriter writer) + { + writer.WriteAutoGeneratedHeader (); + writer.WriteLine (); + + writer.WriteLine ("using System;"); + writer.WriteLine (); + writer.WriteLine ($"namespace {Namespace};"); + writer.WriteLine (); + + base.Write (writer); + } +} diff --git a/build-tools/manifest-attribute-codegen/SourceWriters/AttributeUsageAttr.cs b/build-tools/manifest-attribute-codegen/SourceWriters/AttributeUsageAttr.cs new file mode 100644 index 00000000000..2bffdc634c0 --- /dev/null +++ b/build-tools/manifest-attribute-codegen/SourceWriters/AttributeUsageAttr.cs @@ -0,0 +1,20 @@ +using Xamarin.SourceWriter; + +namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; + +public class AttributeUsageAttr : AttributeWriter +{ + public string Usage { get; set; } + public bool AllowMultiple { get; set; } + + public AttributeUsageAttr (MetadataType type) + { + Usage = type.Usage; + AllowMultiple = type.AllowMultiple; + } + + public override void WriteAttribute (CodeWriter writer) + { + writer.WriteLine ($"[AttributeUsage ({Usage}, AllowMultiple = {(AllowMultiple ? "true" : "false")}, Inherited = false)]"); + } +} diff --git a/build-tools/manifest-attribute-codegen/SourceWriters/ObsoleteAttr.cs b/build-tools/manifest-attribute-codegen/SourceWriters/ObsoleteAttr.cs new file mode 100644 index 00000000000..18d8584bfaa --- /dev/null +++ b/build-tools/manifest-attribute-codegen/SourceWriters/ObsoleteAttr.cs @@ -0,0 +1,18 @@ +using Xamarin.SourceWriter; + +namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; + +public class ObsoleteAttr : AttributeWriter +{ + public string Message { get; set; } + + public ObsoleteAttr (string message) + { + Message = message; + } + + public override void WriteAttribute (CodeWriter writer) + { + writer.WriteLine ($"[Obsolete (\"{Message}\")]"); + } +} diff --git a/build-tools/manifest-attribute-codegen/SourceWriters/SerializableAttr.cs b/build-tools/manifest-attribute-codegen/SourceWriters/SerializableAttr.cs new file mode 100644 index 00000000000..e67bda029fb --- /dev/null +++ b/build-tools/manifest-attribute-codegen/SourceWriters/SerializableAttr.cs @@ -0,0 +1,11 @@ +using Xamarin.SourceWriter; + +namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; + +public class SerializableAttr : AttributeWriter +{ + public override void WriteAttribute (CodeWriter writer) + { + writer.WriteLine ("[Serializable]"); + } +} diff --git a/build-tools/manifest-attribute-codegen/manifest-attribute-codegen.cs b/build-tools/manifest-attribute-codegen/manifest-attribute-codegen.cs deleted file mode 100644 index 864ac947612..00000000000 --- a/build-tools/manifest-attribute-codegen/manifest-attribute-codegen.cs +++ /dev/null @@ -1,224 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Xml; -using System.Xml.Linq; - - -namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator -{ - public class Driver - { - public static void Main (string [] args) - { - var sdk = args.FirstOrDefault () - ?? Environment.GetEnvironmentVariable ("ANDROID_SDK_HOME") - ?? Environment.GetEnvironmentVariable ("ANDROID_SDK_PATH"); - if (sdk == null) - throw new InvalidOperationException ("Pass Android SDK location as the command argument, or specify ANDROID_SDK_HOME or ANDROID_SDK_PATH environment variable"); - - var manifests = Directory.GetDirectories (Path.Combine (sdk, "platforms"), "android-*") - .Select (d => Path.Combine (d, "data", "res", "values", "attrs_manifest.xml")) - .Where (f => File.Exists (f)) - .ToList (); - manifests.Sort (StringComparer.OrdinalIgnoreCase); - var defs = manifests.Select (m => ManifestDefinition.FromFileName (m)); - - var merged = new ManifestDefinition (); - foreach (var def in defs) { - foreach (var el in def.Elements) { - var element = merged.Elements.FirstOrDefault (_ => _.Name == el.Name); - if (element == null) - merged.Elements.Add ((element = new ElementDefinition { - ApiLevel = el.ApiLevel, - Name = el.Name, - Parents = (string []) el.Parents?.Clone (), - })); - foreach (var at in el.Attributes) { - var attribute = element.Attributes.FirstOrDefault (_ => _.Name == at.Name); - if (attribute == null) - element.Attributes.Add ((attribute = new AttributeDefinition { - ApiLevel = at.ApiLevel, - Name = at.Name, - Format = at.Format, - })); - foreach (var en in at.Enums) { - var enumeration = at.Enums.FirstOrDefault (_ => _.Name == en.Name); - if (enumeration == null) - attribute.Enums.Add (new EnumDefinition { - ApiLevel = en.ApiLevel, - Name = en.Name, - Value = en.Value, - }); - } - } - } - } - var sw = new StringWriter (); - merged.WriteXml (sw); - Console.WriteLine (""); - Console.WriteLine (sw.ToString () - .Replace (" api-level='10'", "") - .Replace (" format=''", "") - .Replace (" parent=''", "")); - } - } - - class ManifestDefinition - { - public int ApiLevel { get; set; } - public IList Elements { get; private set; } = new List (); - - public static ManifestDefinition FromFileName (string filePath) - { - var dirName = new FileInfo (filePath).Directory.Parent.Parent.Parent.Name; - var api = int.Parse (dirName.Substring (dirName.IndexOf ('-') + 1)); - return new ManifestDefinition () { - ApiLevel = api, - Elements = XDocument.Load (filePath).Root.Elements ("declare-styleable") - .Select (e => ElementDefinition.FromElement (api, e)) - .ToList () - }; - } - - public void WriteXml (TextWriter w) - { - w.WriteLine (""); - foreach (var e in Elements) - e.WriteXml (w); - w.WriteLine (""); - } - - public void WriteCode (TextWriter w) - { - foreach (var e in Elements) - e.WriteCode (w); - } - } - - class ElementDefinition - { - public int ApiLevel { get; set; } - public string Name { get; set; } - public string [] Parents { get; set; } - public IList Attributes { get; private set; } = new List (); - - public string ActualElementName { - get { return Name.ToActualName (); } - } - - static readonly char [] sep = new char [] {' '}; - - public static ElementDefinition FromElement (int api, XElement e) - { - return new ElementDefinition () { - ApiLevel = api, - Name = e.Attribute ("name").Value, - Parents = e.Attribute ("parent")?.Value?.Split ().Select (s => s.Trim ()).Where (s => !string.IsNullOrWhiteSpace (s)).ToArray (), - Attributes = e.Elements ("attr") - .Select (a => AttributeDefinition.FromElement (api, a)) - .ToList () - }; - } - - public void WriteXml (TextWriter w) - { - w.WriteLine ($" "); - if (Parents != null && Parents.Any ()) - foreach (var p in Parents) - w.WriteLine ($" {p.ToActualName ()}"); - foreach (var a in Attributes) - a.WriteXml (w); - w.WriteLine (" "); - } - - public void WriteCode (TextWriter w) - { - } - } - - class AttributeDefinition - { - public int ApiLevel { get; set; } - public string Name { get; set; } - public string Format { get; set; } - public IList Enums { get; set; } = new List (); - - public static AttributeDefinition FromElement (int api, XElement e) - { - return new AttributeDefinition { - ApiLevel = api, - Name = e.Attribute ("name").Value, - Format = e.Attribute ("format")?.Value, - Enums = e.Elements ("enum") - .Select (n => new EnumDefinition { - ApiLevel = api, - Name = n.Attribute ("name").Value, - Value = n.Attribute ("value").Value, - }) - .ToList () - }; - } - - public void WriteXml (TextWriter w) - { - w.Write ($" "); - foreach (var e in Enums) - w.WriteLine ($" "); - w.WriteLine (" "); - } - else - w.WriteLine (" />"); - } - } - - class EnumDefinition - { - public int ApiLevel { get; set; } - public string Name { get; set; } - public string Value { get; set; } - } - - static class StringExtensions - { - static StringExtensions () - { - // micro unit testing, am so clever! - if (Hyphenate ("AndSoOn") != "and-so-on") - throw new InvalidOperationException ("Am so buggy 1 " + Hyphenate ("AndSoOn")); - if (Hyphenate ("aBigProblem") != "a-big-problem") - throw new InvalidOperationException ("Am so buggy 2"); - if (Hyphenate ("my-two-cents") != "my-two-cents") - throw new InvalidOperationException ("Am so buggy 3"); - } - - public static string Hyphenate (this string s) - { - var sb = new StringBuilder (s.Length * 2); - for (int i = 0; i < s.Length; i++) { - if (char.IsUpper (s [i])) { - if (i > 0) - sb.Append ('-'); - sb.Append (char.ToLowerInvariant (s [i])); - } - else - sb.Append (s [i]); - } - return sb.ToString (); - } - - const string prefix = "AndroidManifest"; - - public static string ToActualName (this string s) - { - s = s.IndexOf ('.') < 0 ? s : s.Substring (s.LastIndexOf ('.') + 1); - - var ret = (s.StartsWith (prefix, StringComparison.Ordinal) ? s.Substring (prefix.Length) : s).Hyphenate (); - return ret.Length == 0 ? "manifest" : ret; - } - } -} diff --git a/build-tools/manifest-attribute-codegen/manifest-attribute-codegen.csproj b/build-tools/manifest-attribute-codegen/manifest-attribute-codegen.csproj new file mode 100644 index 00000000000..0486f1e8aa1 --- /dev/null +++ b/build-tools/manifest-attribute-codegen/manifest-attribute-codegen.csproj @@ -0,0 +1,38 @@ + + + + Exe + $(DotNetStableTargetFramework) + manifest_attribute_codegen + enable + enable + ..\..\bin\Build$(Configuration) + false + + + + + + + + + + + + + + + + + <_ManifestAttributeCodeGen>..\..\bin\Build$(Configuration)\manifest-attribute-codegen.dll + <_ConfigurationFile>$(MSBuildThisFileDirectory)metadata.xml + <_RepositoryBaseDirectory>..\..\ + + + + + + + diff --git a/build-tools/manifest-attribute-codegen/metadata.xml b/build-tools/manifest-attribute-codegen/metadata.xml new file mode 100644 index 00000000000..64baac1a7ca --- /dev/null +++ b/build-tools/manifest-attribute-codegen/metadata.xml @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Mono.Android/Android.App/IntentFilterAttribute.Partial.cs b/src/Mono.Android/Android.App/IntentFilterAttribute.Partial.cs new file mode 100644 index 00000000000..30b8b500a15 --- /dev/null +++ b/src/Mono.Android/Android.App/IntentFilterAttribute.Partial.cs @@ -0,0 +1,36 @@ +using System; + +namespace Android.App; + +public sealed partial class IntentFilterAttribute +{ + public IntentFilterAttribute (string [] actions) + { + if (actions == null) + throw new ArgumentNullException ("actions"); + if (actions.Length < 1) + throw new ArgumentException ("At least one action must be specified.", "actions"); + Actions = actions; + } + + public string [] Actions { get; } + public string []? Categories { get; set; } + public string? DataHost { get; set; } + public string? DataMimeType { get; set; } + public string? DataPath { get; set; } + public string? DataPathPattern { get; set; } + public string? DataPathPrefix { get; set; } + public string? DataPort { get; set; } + public string? DataScheme { get; set; } + public string []? DataHosts { get; set; } + public string []? DataMimeTypes { get; set; } + public string []? DataPaths { get; set; } + public string []? DataPathPatterns { get; set; } + public string []? DataPathPrefixes { get; set; } + public string []? DataPorts { get; set; } + public string []? DataSchemes { get; set; } + public string? DataPathAdvancedPattern { get; set; } + public string []? DataPathAdvancedPatterns { get; set; } + public string? DataPathSuffix { get; set; } + public string []? DataPathSuffixes { get; set; } +} diff --git a/src/Mono.Android/Android.App/IntentFilterAttribute.cs b/src/Mono.Android/Android.App/IntentFilterAttribute.cs index ea9847520d9..3a5bf9c4192 100644 --- a/src/Mono.Android/Android.App/IntentFilterAttribute.cs +++ b/src/Mono.Android/Android.App/IntentFilterAttribute.cs @@ -1,55 +1,29 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + using System; -namespace Android.App { - - [Serializable] - [AttributeUsage (AttributeTargets.Class, - AllowMultiple=true, - Inherited=false)] - public sealed partial class IntentFilterAttribute : Attribute { - - public IntentFilterAttribute (string[] actions) - { - if (actions == null) - throw new ArgumentNullException ("actions"); - if (actions.Length < 1) - throw new ArgumentException ("At least one action must be specified.", "actions"); - Actions = actions; - } - - public string? Icon {get; set;} - public string? Label {get; set;} - public int Priority {get; set;} - public string[] Actions {get; private set;} - public string[]? Categories {get; set;} - public string? DataHost {get; set;} - public string? DataMimeType {get; set;} - public string? DataPath {get; set;} - public string? DataPathPattern {get; set;} - public string? DataPathPrefix {get; set;} - public string? DataPort {get; set;} - public string? DataScheme {get; set;} - public string[]? DataHosts {get; set;} - public string[]? DataMimeTypes {get; set;} - public string[]? DataPaths {get; set;} - public string[]? DataPathPatterns{get; set;} - public string[]? DataPathPrefixes{get; set;} - public string[]? DataPorts {get; set;} - public string[]? DataSchemes {get; set;} -#if ANDROID_23 - // This does not exist on https://developer.android.com/guide/topics/manifest/intent-filter-element.html but on http://developer.android.com/intl/ja/training/app-links/index.html ! (bug #35595) - public bool AutoVerify {get; set;} -#endif -#if ANDROID_25 - public string? RoundIcon {get; set;} -#endif -#if ANDROID_26 - public string? DataPathAdvancedPattern {get; set;} - public string[]? DataPathAdvancedPatterns {get; set;} -#endif -#if ANDROID_31 - public string? DataPathSuffix {get; set;} - public string[]? DataPathSuffixes {get; set;} -#endif - } +namespace Android.App; + +[Serializable] +[AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] +public sealed partial class IntentFilterAttribute : Attribute { + public bool AutoVerify { get; set; } + + public string? Icon { get; set; } + + public string? Label { get; set; } + + public int Priority { get; set; } + + public string? RoundIcon { get; set; } + } diff --git a/src/Mono.Android/Android.App/MetaDataAttribute.Partial.cs b/src/Mono.Android/Android.App/MetaDataAttribute.Partial.cs new file mode 100644 index 00000000000..ca15c4722aa --- /dev/null +++ b/src/Mono.Android/Android.App/MetaDataAttribute.Partial.cs @@ -0,0 +1,11 @@ +using System; + +namespace Android.App; + +public sealed partial class MetaDataAttribute +{ + public MetaDataAttribute (string name) + { + Name = name; + } +} diff --git a/src/Mono.Android/Android.App/MetaDataAttribute.cs b/src/Mono.Android/Android.App/MetaDataAttribute.cs index 36b7c7448f4..42794bac120 100644 --- a/src/Mono.Android/Android.App/MetaDataAttribute.cs +++ b/src/Mono.Android/Android.App/MetaDataAttribute.cs @@ -1,20 +1,25 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + using System; -namespace Android.App { +namespace Android.App; + +[Serializable] +[AttributeUsage (AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = true, Inherited = false)] +public sealed partial class MetaDataAttribute : Attribute { + public string Name { get; private set; } - [Serializable] - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Assembly, - AllowMultiple=true, - Inherited=false)] - public sealed partial class MetaDataAttribute : Attribute { + public string? Resource { get; set; } - public MetaDataAttribute (string name) - { - Name = name; - } + public string? Value { get; set; } - public string Name {get; private set;} - public string? Resource {get; set;} - public string? Value {get; set;} - } } diff --git a/src/Mono.Android/Android.App/PermissionAttribute.cs b/src/Mono.Android/Android.App/PermissionAttribute.cs index 747ea1c9a91..997ff852d16 100644 --- a/src/Mono.Android/Android.App/PermissionAttribute.cs +++ b/src/Mono.Android/Android.App/PermissionAttribute.cs @@ -1,29 +1,37 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + using System; -using Android.Content.PM; -using Android.Views; - -namespace Android.App { - - [Serializable] - [AttributeUsage (AttributeTargets.Assembly, - AllowMultiple=true, - Inherited=false)] - public sealed partial class PermissionAttribute : Attribute { - - public PermissionAttribute () - { - } - - public string? Description {get; set;} - public string? Icon {get; set;} - public string? Label {get; set;} - public string? Name {get; set;} - public string? PermissionGroup {get; set;} - public Protection ProtectionLevel {get; set;} -#if ANDROID_25 - public string? RoundIcon {get; set;} -#endif +namespace Android.App; + +[Serializable] +[AttributeUsage (AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] +public sealed partial class PermissionAttribute : Attribute { + public PermissionAttribute () + { } -} + public string? Description { get; set; } + + public string? Icon { get; set; } + + public string? Label { get; set; } + + public string? Name { get; set; } + + public string? PermissionGroup { get; set; } + + public Android.Content.PM.Protection ProtectionLevel { get; set; } + + public string? RoundIcon { get; set; } + +} diff --git a/src/Mono.Android/Android.App/PermissionGroupAttribute.cs b/src/Mono.Android/Android.App/PermissionGroupAttribute.cs index 3e2bf5fe192..41df8b07205 100644 --- a/src/Mono.Android/Android.App/PermissionGroupAttribute.cs +++ b/src/Mono.Android/Android.App/PermissionGroupAttribute.cs @@ -1,27 +1,33 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + using System; -using Android.Content.PM; -using Android.Views; +namespace Android.App; -namespace Android.App { +[Serializable] +[AttributeUsage (AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] +public sealed partial class PermissionGroupAttribute : Attribute { + public PermissionGroupAttribute () + { + } - [Serializable] - [AttributeUsage (AttributeTargets.Assembly, - AllowMultiple=true, - Inherited=false)] - public sealed partial class PermissionGroupAttribute : Attribute { + public string? Description { get; set; } - public PermissionGroupAttribute () - { - } + public string? Icon { get; set; } - public string? Description {get; set;} - public string? Icon {get; set;} - public string? Label {get; set;} - public string? Name {get; set;} -#if ANDROID_25 - public string? RoundIcon {get; set;} -#endif - } -} + public string? Label { get; set; } + + public string? Name { get; set; } + public string? RoundIcon { get; set; } + +} diff --git a/src/Mono.Android/Android.App/PermissionTreeAttribute.cs b/src/Mono.Android/Android.App/PermissionTreeAttribute.cs index b530422a9d6..7134b1940ad 100644 --- a/src/Mono.Android/Android.App/PermissionTreeAttribute.cs +++ b/src/Mono.Android/Android.App/PermissionTreeAttribute.cs @@ -1,26 +1,31 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + using System; -using Android.Content.PM; -using Android.Views; +namespace Android.App; -namespace Android.App { +[Serializable] +[AttributeUsage (AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)] +public sealed partial class PermissionTreeAttribute : Attribute { + public PermissionTreeAttribute () + { + } - [Serializable] - [AttributeUsage (AttributeTargets.Assembly, - AllowMultiple=false, - Inherited=false)] - public sealed partial class PermissionTreeAttribute : Attribute { + public string? Icon { get; set; } - public PermissionTreeAttribute () - { - } + public string? Label { get; set; } - public string? Icon {get; set;} - public string? Label {get; set;} - public string? Name {get; set;} -#if ANDROID_25 - public string? RoundIcon {get; set;} -#endif - } -} + public string? Name { get; set; } + + public string? RoundIcon { get; set; } +} diff --git a/src/Mono.Android/Android.App/UsesConfigurationAttribute.cs b/src/Mono.Android/Android.App/UsesConfigurationAttribute.cs index 283c6f336aa..7e4b8da9564 100644 --- a/src/Mono.Android/Android.App/UsesConfigurationAttribute.cs +++ b/src/Mono.Android/Android.App/UsesConfigurationAttribute.cs @@ -1,25 +1,33 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + using System; -using Android.Content.PM; -using Android.Views; +namespace Android.App; -namespace Android.App { +[Serializable] +[AttributeUsage (AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] +public sealed partial class UsesConfigurationAttribute : Attribute { + public UsesConfigurationAttribute () + { + } - [Serializable] - [AttributeUsage (AttributeTargets.Assembly, - AllowMultiple=true, - Inherited=false)] - public sealed partial class UsesConfigurationAttribute : Attribute { + public bool ReqFiveWayNav { get; set; } - public UsesConfigurationAttribute () - { - } + public bool ReqHardKeyboard { get; set; } - public bool ReqFiveWayNav { get; set; } - public bool ReqHardKeyboard { get; set; } - public string ReqKeyboardType { get; set; } - public string ReqNavigation { get; set; } - public string ReqTouchScreen { get; set; } - } -} + public string? ReqKeyboardType { get; set; } + + public string? ReqNavigation { get; set; } + public string? ReqTouchScreen { get; set; } + +} diff --git a/src/Mono.Android/Android.App/UsesFeatureAttribute.Partial.cs b/src/Mono.Android/Android.App/UsesFeatureAttribute.Partial.cs new file mode 100644 index 00000000000..9f8e7dea0e5 --- /dev/null +++ b/src/Mono.Android/Android.App/UsesFeatureAttribute.Partial.cs @@ -0,0 +1,11 @@ +using System; + +namespace Android.App; + +public sealed partial class UsesFeatureAttribute +{ + public UsesFeatureAttribute (string name) + { + Name = name; + } +} diff --git a/src/Mono.Android/Android.App/UsesFeatureAttribute.cs b/src/Mono.Android/Android.App/UsesFeatureAttribute.cs index c8e555e80fb..53f675e7485 100644 --- a/src/Mono.Android/Android.App/UsesFeatureAttribute.cs +++ b/src/Mono.Android/Android.App/UsesFeatureAttribute.cs @@ -1,30 +1,31 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + using System; -namespace Android.App -{ - [Serializable] - [AttributeUsage (AttributeTargets.Assembly, - AllowMultiple=true, - Inherited=false)] - public sealed partial class UsesFeatureAttribute : Attribute +namespace Android.App; + +[Serializable] +[AttributeUsage (AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] +public sealed partial class UsesFeatureAttribute : Attribute { + public UsesFeatureAttribute () { - public UsesFeatureAttribute () - { - } - - public UsesFeatureAttribute (string name) - { - Name = name; - } - - public string? Name {get; private set;} -#if ANDROID_7 - public bool Required {get; set;} -#endif - public int GLESVersion {get; set;} -#if ANDROID_24 - public int Version { get; private set; } -#endif } -} + public int GLESVersion { get; set; } + + public string? Name { get; private set; } + + public bool Required { get; set; } + + public int Version { get; private set; } + +} diff --git a/src/Mono.Android/Android.App/UsesLibraryAttribute.Partial.cs b/src/Mono.Android/Android.App/UsesLibraryAttribute.Partial.cs new file mode 100644 index 00000000000..addda757289 --- /dev/null +++ b/src/Mono.Android/Android.App/UsesLibraryAttribute.Partial.cs @@ -0,0 +1,16 @@ +using System; + +namespace Android.App; + +public sealed partial class UsesLibraryAttribute +{ + public UsesLibraryAttribute (string name) + { + Name = name; + } + + public UsesLibraryAttribute (string name, bool required) : this (name) + { + Required = required; + } +} diff --git a/src/Mono.Android/Android.App/UsesLibraryAttribute.cs b/src/Mono.Android/Android.App/UsesLibraryAttribute.cs index aab26eeafd1..22ad989714e 100644 --- a/src/Mono.Android/Android.App/UsesLibraryAttribute.cs +++ b/src/Mono.Android/Android.App/UsesLibraryAttribute.cs @@ -1,31 +1,27 @@ -using System; +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using Android.Content.PM; -using Android.Views; +#nullable enable -namespace Android.App { +using System; - [Serializable] - [AttributeUsage (AttributeTargets.Assembly | AttributeTargets.Class, - AllowMultiple=true, - Inherited=false)] - public sealed partial class UsesLibraryAttribute : Attribute { +namespace Android.App; - public UsesLibraryAttribute () - { - } +[Serializable] +[AttributeUsage (AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = true, Inherited = false)] +public sealed partial class UsesLibraryAttribute : Attribute { + public UsesLibraryAttribute () + { + } - public UsesLibraryAttribute (string name) - { - Name = name; - } + public string? Name { get; set; } - public UsesLibraryAttribute (string name, bool required) : this (name) - { - Required = required; - } + public bool Required { get; set; } - public string? Name {get; set;} - public bool Required {get; set;} - } } diff --git a/src/Mono.Android/Android.Content/GrantUriPermissionAttribute.cs b/src/Mono.Android/Android.Content/GrantUriPermissionAttribute.cs index f65127f20f4..2fc2f219e5b 100644 --- a/src/Mono.Android/Android.Content/GrantUriPermissionAttribute.cs +++ b/src/Mono.Android/Android.Content/GrantUriPermissionAttribute.cs @@ -1,21 +1,29 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + using System; -using Android.Views; +namespace Android.Content; -namespace Android.Content { +[Serializable] +[AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] +public partial class GrantUriPermissionAttribute : Attribute { + public GrantUriPermissionAttribute () + { + } - [Serializable] - [AttributeUsage (AttributeTargets.Class, - AllowMultiple=true, - Inherited=false)] - public partial class GrantUriPermissionAttribute : Attribute { + public string? Path { get; set; } - public GrantUriPermissionAttribute () - { - } + public string? PathPattern { get; set; } + + public string? PathPrefix { get; set; } - public string? Path {get; set;} - public string? PathPattern {get; set;} - public string? PathPrefix {get; set;} - } } diff --git a/src/Mono.Android/Mono.Android.csproj b/src/Mono.Android/Mono.Android.csproj index 1191832e9fd..202ebb04b7e 100644 --- a/src/Mono.Android/Mono.Android.csproj +++ b/src/Mono.Android/Mono.Android.csproj @@ -79,6 +79,10 @@ Crc64.Table.cs + + + + diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj index 2588f29e729..2f60179a14d 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj @@ -85,9 +85,15 @@ Mono.Android\IntentFilterAttribute.cs + + Mono.Android\IntentFilterAttribute.Partial.cs + Mono.Android\MetaDataAttribute.cs + + Mono.Android\MetaDataAttribute.Partial.cs + Mono.Android\GrantUriPermissionAttribute.cs @@ -106,6 +112,9 @@ Mono.Android\UsesLibraryAttribute.cs + + Mono.Android\UsesLibraryAttribute.Partial.cs + Mono.Android\UsesPermissionAttribute.cs @@ -124,6 +133,9 @@ Mono.Android\UsesFeatureAttribute.cs + + Mono.Android\UsesFeatureAttribute.Partial.cs + Mono.Android\SupportsGLTextureAttribute.cs diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.Partial.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.Partial.cs new file mode 100644 index 00000000000..3e6b0316fc6 --- /dev/null +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.Partial.cs @@ -0,0 +1,13 @@ +using System; +using Android.Views; + +namespace Android.App; + +public sealed partial class ActivityAttribute +{ + [Obsolete ("There is no //activity/@android:layoutDirection attribute. This was a mistake. " + + "Perhaps you wanted ConfigurationChanges=ConfigChanges.LayoutDirection?")] + public LayoutDirection LayoutDirection { get; set; } + + public bool MainLauncher { get; set; } +} diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.cs index a6145ce70ae..fd92917eed1 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.cs @@ -1,138 +1,128 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + using System; -using Android.Content.PM; -using Android.Views; - -namespace Android.App -{ - - [Serializable] - [AttributeUsage (AttributeTargets.Class, - AllowMultiple=false, - Inherited=false)] - public sealed partial class ActivityAttribute : Attribute, Java.Interop.IJniNameProviderAttribute { - - public ActivityAttribute () - { - } - - public string? Name {get; set;} - -#if ANDROID_20 - public bool AllowEmbedded {get; set;} -#endif - public bool AllowTaskReparenting {get; set;} - public bool AlwaysRetainTaskState {get; set;} -#if ANDROID_21 - public bool AutoRemoveFromRecents {get; set;} -#endif -#if ANDROID_20 - public string? Banner {get; set;} -#endif - public bool ClearTaskOnLaunch {get; set;} -#if ANDROID_26 - public string? ColorMode {get; set;} -#endif - public ConfigChanges ConfigurationChanges {get; set;} - public string? Description {get; set;} -#if ANDROID_24 - public bool DirectBootAware {get; set;} -#endif -#if ANDROID_21 - public DocumentLaunchMode DocumentLaunchMode {get; set;} -#endif -#if ANDROID_24 - public string? EnableVrMode {get; set;} -#endif - public bool Enabled {get; set;} - public bool ExcludeFromRecents {get; set;} - public bool Exported {get; set;} - public bool FinishOnCloseSystemDialogs {get; set;} - public bool FinishOnTaskLaunch {get; set;} -#if ANDROID_11 - public bool HardwareAccelerated {get; set;} -#endif - public string? Icon {get; set;} - public string? Label {get; set;} - public LaunchMode LaunchMode {get; set;} -#if ANDROID_23 - public string? LockTaskMode {get; set;} -#endif -#if ANDROID_11 - public string? Logo {get; set;} -#endif -#if ANDROID_17 - [Obsolete ("There is no //activity/@android:layoutDirection attribute. This was a mistake. " + - "Perhaps you wanted ConfigurationChanges=ConfigChanges.LayoutDirection?")] - public LayoutDirection LayoutDirection {get; set;} -#endif - public bool MainLauncher {get; set;} -#if ANDROID_26 - public float MaxAspectRatio {get; set;} -#endif -#if ANDROID_21 - public int MaxRecents {get; set;} -#endif - public bool MultiProcess {get; set;} - public bool NoHistory {get; set;} -#if ANDROID_16 - public Type? ParentActivity {get; set;} -#endif - public string? Permission {get; set;} -#if ANDROID_21 - public ActivityPersistableMode PersistableMode {get; set;} -#endif - public string? Process {get; set;} -#if ANDROID_26 - public ConfigChanges RecreateOnConfigChanges {get; set;} -#endif -#if ANDROID_21 - public bool RelinquishTaskIdentity {get; set;} -#endif -#if ANDROID_24 - public bool ResizeableActivity {get;set;} -#endif -#if ANDROID_21 - public bool ResumeWhilePausing {get; set;} -#endif -#if ANDROID_26 - public WindowRotationAnimation RotationAnimation {get; set;} -#endif -#if ANDROID_25 - public string? RoundIcon {get; set;} -#endif -#if ANDROID_23 - public bool ShowForAllUsers {get; set;} -#endif -#if ANDROID_17 - [Obsolete ("Please use ShowForAllUsers instead.")] - public bool ShowOnLockScreen {get; set;} -#endif -#if ANDROID_24 - public bool SupportsPictureInPicture {get;set;} -#endif - public ScreenOrientation ScreenOrientation {get; set;} -#if ANDROID_27 - public bool ShowWhenLocked {get; set;} -#endif -#if ANDROID_17 - public bool SingleUser {get; set;} -#endif - public bool StateNotNeeded {get; set;} - public string? TaskAffinity {get; set;} - public string? Theme {get; set;} -#if ANDROID_27 - public bool TurnScreenOn {get; set;} -#endif -#if ANDROID_14 - public UiOptions UiOptions {get; set;} -#endif -#if ANDROID_26 - public bool VisibleToInstantApps {get; set;} -#endif - public SoftInput WindowSoftInputMode {get; set;} -#if ANDROID_11 // this is not documented on http://developer.android.com/guide/topics/manifest/activity-element.html but on https://developers.google.com/glass/develop/gdk/immersions - public bool Immersive {get; set;} -#endif +namespace Android.App; + +[Serializable] +[AttributeUsage (AttributeTargets.Class, AllowMultiple = false, Inherited = false)] +public sealed partial class ActivityAttribute : Attribute, Java.Interop.IJniNameProviderAttribute { + public ActivityAttribute () + { } + + public bool AllowEmbedded { get; set; } + + public bool AllowTaskReparenting { get; set; } + + public bool AlwaysRetainTaskState { get; set; } + + public bool AutoRemoveFromRecents { get; set; } + + public string? Banner { get; set; } + + public bool ClearTaskOnLaunch { get; set; } + + public string? ColorMode { get; set; } + + public Android.Content.PM.ConfigChanges ConfigurationChanges { get; set; } + + public string? Description { get; set; } + + public bool DirectBootAware { get; set; } + + public Android.Content.PM.DocumentLaunchMode DocumentLaunchMode { get; set; } + + public bool Enabled { get; set; } + + public string? EnableVrMode { get; set; } + + public bool ExcludeFromRecents { get; set; } + + public bool Exported { get; set; } + + public bool FinishOnCloseSystemDialogs { get; set; } + + public bool FinishOnTaskLaunch { get; set; } + + public bool HardwareAccelerated { get; set; } + + public string? Icon { get; set; } + + public bool Immersive { get; set; } + + public string? Label { get; set; } + + public Android.Content.PM.LaunchMode LaunchMode { get; set; } + + public string? LockTaskMode { get; set; } + + public string? Logo { get; set; } + + public float MaxAspectRatio { get; set; } + + public int MaxRecents { get; set; } + + public bool MultiProcess { get; set; } + + public string? Name { get; set; } + + public bool NoHistory { get; set; } + + public Type? ParentActivity { get; set; } + + public string? Permission { get; set; } + + public Android.Content.PM.ActivityPersistableMode PersistableMode { get; set; } + + public string? Process { get; set; } + + public Android.Content.PM.ConfigChanges RecreateOnConfigChanges { get; set; } + + public bool RelinquishTaskIdentity { get; set; } + + public bool ResizeableActivity { get; set; } + + public bool ResumeWhilePausing { get; set; } + + public Android.Views.WindowRotationAnimation RotationAnimation { get; set; } + + public string? RoundIcon { get; set; } + + public Android.Content.PM.ScreenOrientation ScreenOrientation { get; set; } + + public bool ShowForAllUsers { get; set; } + + [Obsolete ("Please use ShowForAllUsers instead.")] + public bool ShowOnLockScreen { get; set; } + + public bool ShowWhenLocked { get; set; } + + public bool SingleUser { get; set; } + + public bool StateNotNeeded { get; set; } + + public bool SupportsPictureInPicture { get; set; } + + public string? TaskAffinity { get; set; } + + public string? Theme { get; set; } + + public bool TurnScreenOn { get; set; } + + public Android.Content.PM.UiOptions UiOptions { get; set; } + + public bool VisibleToInstantApps { get; set; } + + public Android.Views.SoftInput WindowSoftInputMode { get; set; } + } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ApplicationAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ApplicationAttribute.cs index 0864ba11923..f594a51cbed 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ApplicationAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ApplicationAttribute.cs @@ -1,93 +1,97 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + using System; -using Android.Content.PM; -using Android.Views; - -namespace Android.App { - - [Serializable] - [AttributeUsage (AttributeTargets.Assembly | AttributeTargets.Class, - AllowMultiple=false, - Inherited=false)] - public sealed partial class ApplicationAttribute : Attribute, Java.Interop.IJniNameProviderAttribute { - - public ApplicationAttribute () - { - } - - public string? Name {get; set;} - - public bool AllowBackup {get; set;} - public bool AllowClearUserData {get; set;} - public bool AllowTaskReparenting {get; set;} -#if ANDROID_8 - public Type? BackupAgent {get; set;} -#endif -#if ANDROID_24 - public bool BackupInForeground {get; set;} -#endif -#if ANDROID_21 - public string? Banner {get; set;} -#endif - public bool Debuggable {get; set;} - public string? Description {get; set;} -#if ANDROID_24 - public bool DirectBootAware {get; set;} -#endif - public bool Enabled {get; set;} -#if ANDROID_23 - public bool ExtractNativeLibs {get; set;} - public bool FullBackupContent {get; set;} -#endif -#if ANDROID_21 - public bool FullBackupOnly {get; set;} -#endif -#if ANDROID_11 - public bool HardwareAccelerated {get; set;} -#endif - public bool HasCode {get; set;} - public string? Icon {get; set;} - public bool KillAfterRestore {get; set;} -#if ANDROID_11 - public bool LargeHeap {get; set;} -#endif - public string? Label {get; set;} -#if ANDROID_11 - public string? Logo {get; set;} -#endif - public Type? ManageSpaceActivity {get; set;} -#if ANDROID_26 - public string? NetworkSecurityConfig {get; set;} -#endif - public string? Permission {get; set;} - public bool Persistent {get; set;} - public string? Process {get; set;} -#if ANDROID_18 - public string? RequiredAccountType {get; set;} -#endif - public bool RestoreAnyVersion {get; set;} -#if ANDROID_18 - public string? RestrictedAccountType {get; set;} -#endif -#if ANDROID_25 - public string? RoundIcon {get; set;} -#endif -#if ANDROID_17 - public bool SupportsRtl {get; set;} -#endif - public string? TaskAffinity {get; set;} - public string? Theme {get; set;} -#if ANDROID_14 - public UiOptions UiOptions {get; set;} -#endif -#if ANDROID_23 - public bool UsesCleartextTraffic {get; set;} -#endif -#if ANDROID_10 - public bool VMSafeMode {get; set;} -#endif -#if ANDROID_24 - public bool ResizeableActivity {get; set;} -#endif +namespace Android.App; + +[Serializable] +[AttributeUsage (AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = false, Inherited = false)] +public sealed partial class ApplicationAttribute : Attribute, Java.Interop.IJniNameProviderAttribute { + public ApplicationAttribute () + { } + + public bool AllowBackup { get; set; } + + public bool AllowClearUserData { get; set; } + + public bool AllowTaskReparenting { get; set; } + + public Type? BackupAgent { get; set; } + + public bool BackupInForeground { get; set; } + + public string? Banner { get; set; } + + public bool Debuggable { get; set; } + + public string? Description { get; set; } + + public bool DirectBootAware { get; set; } + + public bool Enabled { get; set; } + + public bool ExtractNativeLibs { get; set; } + + public bool FullBackupContent { get; set; } + + public bool FullBackupOnly { get; set; } + + public bool HardwareAccelerated { get; set; } + + public bool HasCode { get; set; } + + public string? Icon { get; set; } + + public bool KillAfterRestore { get; set; } + + public string? Label { get; set; } + + public bool LargeHeap { get; set; } + + public string? Logo { get; set; } + + public Type? ManageSpaceActivity { get; set; } + + public string? Name { get; set; } + + public string? NetworkSecurityConfig { get; set; } + + public string? Permission { get; set; } + + public bool Persistent { get; set; } + + public string? Process { get; set; } + + public string? RequiredAccountType { get; set; } + + public bool ResizeableActivity { get; set; } + + public bool RestoreAnyVersion { get; set; } + + public string? RestrictedAccountType { get; set; } + + public string? RoundIcon { get; set; } + + public bool SupportsRtl { get; set; } + + public string? TaskAffinity { get; set; } + + public string? Theme { get; set; } + + public Android.Content.PM.UiOptions UiOptions { get; set; } + + public bool UsesCleartextTraffic { get; set; } + + public bool VMSafeMode { get; set; } + } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/InstrumentationAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/InstrumentationAttribute.cs index a35c9f59c22..6edc553b90c 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.App/InstrumentationAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/InstrumentationAttribute.cs @@ -1,29 +1,39 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + using System; -namespace Android.App { - - [Serializable] - [AttributeUsage (AttributeTargets.Assembly | AttributeTargets.Class, - AllowMultiple=true, - Inherited=false)] - public sealed partial class InstrumentationAttribute : Attribute, Java.Interop.IJniNameProviderAttribute { - - public InstrumentationAttribute () - { - } - - public bool FunctionalTest {get; set;} - public bool HandleProfiling {get; set;} - public string? Icon {get; set;} - public string? Label {get; set;} - public string? Name {get; set;} -#if ANDROID_25 - public string? RoundIcon {get; set;} -#endif - public string? TargetPackage {get; set;} -#if ANDROID_26 - public string? TargetProcesses {get; set;} -#endif +namespace Android.App; + +[Serializable] +[AttributeUsage (AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = true, Inherited = false)] +public sealed partial class InstrumentationAttribute : Attribute, Java.Interop.IJniNameProviderAttribute { + public InstrumentationAttribute () + { } -} + public bool FunctionalTest { get; set; } + + public bool HandleProfiling { get; set; } + + public string? Icon { get; set; } + + public string? Label { get; set; } + + public string? Name { get; set; } + + public string? RoundIcon { get; set; } + + public string? TargetPackage { get; set; } + + public string? TargetProcesses { get; set; } + +} diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/LayoutAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/LayoutAttribute.cs index 98394bb0912..15d52290f66 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.App/LayoutAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/LayoutAttribute.cs @@ -1,23 +1,33 @@ -#if ANDROID_24 -using System; +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable -using Android.Content.PM; -using Android.Views; +using System; -namespace Android.App -{ +namespace Android.App; - [Serializable] - [AttributeUsage (AttributeTargets.Class, - AllowMultiple = false, - Inherited = false)] - public sealed partial class LayoutAttribute : Attribute +[Serializable] +[AttributeUsage (AttributeTargets.Class, AllowMultiple = false, Inherited = false)] +public sealed partial class LayoutAttribute : Attribute { + public LayoutAttribute () { - public string? DefaultWidth { get; set; } - public string? DefaultHeight { get; set; } - public string? Gravity { get; set; } - public string? MinHeight { get; set; } - public string? MinWidth { get; set; } } + + public string? DefaultHeight { get; set; } + + public string? DefaultWidth { get; set; } + + public string? Gravity { get; set; } + + public string? MinHeight { get; set; } + + public string? MinWidth { get; set; } + } -#endif diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ServiceAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ServiceAttribute.cs index 50752aaa9cd..2eaf442b666 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ServiceAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ServiceAttribute.cs @@ -1,39 +1,45 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + using System; -using Android.Content.PM; -using Android.Views; - -namespace Android.App { - - [Serializable] - [AttributeUsage (AttributeTargets.Class, - AllowMultiple=false, - Inherited=false)] - public sealed partial class ServiceAttribute : Attribute, Java.Interop.IJniNameProviderAttribute { - - public ServiceAttribute () - { - } - - public string? Name {get; set;} - -#if ANDROID_24 - public bool DirectBootAware {get; set;} -#endif - public bool Enabled {get; set;} - public bool Exported {get; set;} -#if ANDROID_29 - public ForegroundService ForegroundServiceType {get; set;} -#endif - public string? Icon {get; set;} -#if ANDROID_16 - public bool IsolatedProcess {get; set;} -#endif - public string? Label {get; set;} - public string? Permission {get; set;} - public string? Process {get; set;} -#if ANDROID_25 - public string? RoundIcon {get; set;} -#endif +namespace Android.App; + +[Serializable] +[AttributeUsage (AttributeTargets.Class, AllowMultiple = false, Inherited = false)] +public sealed partial class ServiceAttribute : Attribute, Java.Interop.IJniNameProviderAttribute { + public ServiceAttribute () + { } + + public bool DirectBootAware { get; set; } + + public bool Enabled { get; set; } + + public bool Exported { get; set; } + + public Android.Content.PM.ForegroundService ForegroundServiceType { get; set; } + + public string? Icon { get; set; } + + public bool IsolatedProcess { get; set; } + + public string? Label { get; set; } + + public string? Name { get; set; } + + public string? Permission { get; set; } + + public string? Process { get; set; } + + public string? RoundIcon { get; set; } + } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.Content/BroadcastReceiverAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.Content/BroadcastReceiverAttribute.cs index de19b6bcf03..e2b7fedaa40 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.Content/BroadcastReceiverAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.Content/BroadcastReceiverAttribute.cs @@ -1,28 +1,43 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + using System; -namespace Android.Content { - - [Serializable] - [AttributeUsage (AttributeTargets.Class, - AllowMultiple=false, - Inherited=false)] - public partial class BroadcastReceiverAttribute : Attribute, Java.Interop.IJniNameProviderAttribute { - - public BroadcastReceiverAttribute () - { - } - - public bool DirectBootAware {get; set;} - public bool Enabled {get; set;} - public bool Exported {get; set;} - public string? Description {get; set;} - public string? Icon {get; set;} - public string? Label {get; set;} - public string? Name {get; set;} - public string? Permission {get; set;} - public string? Process {get; set;} -#if ANDROID_25 - public string? RoundIcon {get; set;} -#endif +namespace Android.Content; + +[Serializable] +[AttributeUsage (AttributeTargets.Class, AllowMultiple = false, Inherited = false)] +public partial class BroadcastReceiverAttribute : Attribute, Java.Interop.IJniNameProviderAttribute { + public BroadcastReceiverAttribute () + { } + + public string? Description { get; set; } + + public bool DirectBootAware { get; set; } + + public bool Enabled { get; set; } + + public bool Exported { get; set; } + + public string? Icon { get; set; } + + public string? Label { get; set; } + + public string? Name { get; set; } + + public string? Permission { get; set; } + + public string? Process { get; set; } + + public string? RoundIcon { get; set; } + } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.Partial.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.Partial.cs new file mode 100644 index 00000000000..142e7a09eb3 --- /dev/null +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.Partial.cs @@ -0,0 +1,15 @@ +using System; + +namespace Android.Content; + +public partial class ContentProviderAttribute +{ + public ContentProviderAttribute (string [] authorities) + { + if (authorities == null) + throw new ArgumentNullException ("authorities"); + if (authorities.Length < 1) + throw new ArgumentException ("At least one authority must be specified.", "authorities"); + Authorities = authorities; + } +} diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.cs index c171dc079f8..41976ef02cb 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.cs @@ -1,41 +1,51 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + using System; -namespace Android.Content { - - [Serializable] - [AttributeUsage (AttributeTargets.Class, - AllowMultiple=false, - Inherited=false)] - public partial class ContentProviderAttribute : Attribute, Java.Interop.IJniNameProviderAttribute { - - public ContentProviderAttribute (string[] authorities) - { - if (authorities == null) - throw new ArgumentNullException ("authorities"); - if (authorities.Length < 1) - throw new ArgumentException ("At least one authority must be specified.", "authorities"); - Authorities = authorities; - } - - public string[] Authorities {get; private set;} -#if ANDROID_24 - public bool DirectBootAware {get; set;} -#endif - public bool Enabled {get; set;} - public bool Exported {get; set;} - public bool GrantUriPermissions {get; set;} - public string? Icon {get; set;} - public int InitOrder {get; set;} - public string? Label {get; set;} - public bool MultiProcess {get; set;} - public string? Name {get; set;} - public string? Permission {get; set;} - public string? Process {get; set;} - public string? ReadPermission {get; set;} -#if ANDROID_25 - public string? RoundIcon {get; set;} -#endif - public bool Syncable {get; set;} - public string? WritePermission {get; set;} - } +namespace Android.Content; + +[Serializable] +[AttributeUsage (AttributeTargets.Class, AllowMultiple = false, Inherited = false)] +public partial class ContentProviderAttribute : Attribute, Java.Interop.IJniNameProviderAttribute { + public string[] Authorities { get; private set; } + + public bool DirectBootAware { get; set; } + + public bool Enabled { get; set; } + + public bool Exported { get; set; } + + public bool GrantUriPermissions { get; set; } + + public string? Icon { get; set; } + + public int InitOrder { get; set; } + + public string? Label { get; set; } + + public bool MultiProcess { get; set; } + + public string? Name { get; set; } + + public string? Permission { get; set; } + + public string? Process { get; set; } + + public string? ReadPermission { get; set; } + + public string? RoundIcon { get; set; } + + public bool Syncable { get; set; } + + public string? WritePermission { get; set; } + } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Xamarin.Android.NamingCustomAttributes.projitems b/src/Xamarin.Android.NamingCustomAttributes/Xamarin.Android.NamingCustomAttributes.projitems index e66fd58d3e0..93c4f7dc19d 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Xamarin.Android.NamingCustomAttributes.projitems +++ b/src/Xamarin.Android.NamingCustomAttributes/Xamarin.Android.NamingCustomAttributes.projitems @@ -11,12 +11,14 @@ + + From 42869923420b7b0d3564d22d4a39c137c6b2ca74 Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Thu, 7 Mar 2024 11:13:00 -1000 Subject: [PATCH 2/4] =?UTF-8?q?=EF=BB=BFGenerate=20mappings=20used=20by=20?= =?UTF-8?q?`Xamarin.Android.Build.Tasks`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Documentation/workflow/HowToAddNewApiLevel.md | 7 +- .../Extensions/StringExtensions.cs | 48 ++- .../Models/AttributeDefinition.cs | 10 + .../Models/MetadataSource.cs | 128 ++++--- .../manifest-attribute-codegen/Program.cs | 14 +- .../manifest-attribute-codegen/README.md | 102 +++++- .../SourceWriters/AttributeDataClass.cs | 46 ++- .../SourceWriters/AttributeMappingField.cs | 18 + .../AttributeMappingManualInitializer.cs | 19 + .../AttributeMappingStaticConstructor.cs | 45 +++ .../manifest-attribute-codegen/metadata.xml | 132 ++++++- .../Android.App/MetaDataAttribute.cs | 29 ++ .../Android.App/PermissionAttribute.cs | 53 +++ .../Android.App/PermissionGroupAttribute.cs | 41 +++ .../Android.App/PermissionTreeAttribute.cs | 35 ++ .../Android.App/UsesConfigurationAttribute.cs | 41 +++ .../Android.App/UsesFeatureAttribute.cs | 29 ++ .../Android.App/UsesLibraryAttribute.cs | 23 ++ .../UsesPermissionAttribute.Partial.cs | 9 + .../Android.App/UsesPermissionAttribute.cs | 60 +++- .../GrantUriPermissionAttribute.cs | 29 ++ src/Mono.Android/Mono.Android.csproj | 1 + .../Mono.Android/ActivityAttribute.Partial.cs | 331 +----------------- .../ApplicationAttribute.Partial.cs | 235 ++----------- .../BroadcastReceiverAttribute.Partial.cs | 57 --- .../ContentProviderAttribute.Partial.cs | 94 +---- .../GrantUriPermissionAttribute.Partial.cs | 19 - .../InstrumentationAttribute.Partial.cs | 47 --- .../Mono.Android/LayoutAttribute.Partial.cs | 29 -- .../Mono.Android/MetaDataAttribute.Partial.cs | 19 - .../PermissionAttribute.Partial.cs | 41 --- .../PermissionGroupAttribute.Partial.cs | 31 -- .../PermissionTreeAttribute.Partial.cs | 26 -- .../Mono.Android/ServiceAttribute.Partial.cs | 63 ---- .../UsesConfigurationAttribute.Partial.cs | 31 -- .../UsesFeatureAttribute.Partial.cs | 35 +- .../UsesLibraryAttribute.Partial.cs | 14 - .../UsesPermissionAttribute.Partial.cs | 16 - .../Xamarin.Android.Build.Tasks.csproj | 5 +- .../Android.App/ActivityAttribute.cs | 317 +++++++++++++++++ .../Android.App/ApplicationAttribute.cs | 215 ++++++++++++ .../Android.App/InstrumentationAttribute.cs | 59 ++++ .../Android.App/LayoutAttribute.cs | 41 +++ .../Android.App/ServiceAttribute.cs | 77 ++++ .../BroadcastReceiverAttribute.cs | 71 ++++ .../ContentProviderAttribute.cs | 101 ++++++ 46 files changed, 1737 insertions(+), 1156 deletions(-) create mode 100644 build-tools/manifest-attribute-codegen/SourceWriters/AttributeMappingField.cs create mode 100644 build-tools/manifest-attribute-codegen/SourceWriters/AttributeMappingManualInitializer.cs create mode 100644 build-tools/manifest-attribute-codegen/SourceWriters/AttributeMappingStaticConstructor.cs create mode 100644 src/Mono.Android/Android.App/UsesPermissionAttribute.Partial.cs diff --git a/Documentation/workflow/HowToAddNewApiLevel.md b/Documentation/workflow/HowToAddNewApiLevel.md index b5479f1942d..ee53e983de8 100644 --- a/Documentation/workflow/HowToAddNewApiLevel.md +++ b/Documentation/workflow/HowToAddNewApiLevel.md @@ -13,7 +13,7 @@ the more manual parts like enumification that will likely change as the APIs mat - Add new level to `/build-tools/xaprepare/xaprepare/ConfigAndData/Dependencies/AndroidToolchain.cs`: - `new AndroidPlatformComponent ("platform-S_r01", apiLevel: "S", pkgRevision: "1"),` -At this point, you can run `Xamarin.Android.sln /t:Prepare` using your usual mechanism, and +At this point, you can run `Xamarin.Android.sln -t:Prepare` using your usual mechanism, and the new platform will be downloaded to your local Android SDK. ### Generate `params.txt` File @@ -49,6 +49,11 @@ the new platform will be downloaded to your local Android SDK. - Add required metadata fixes in `/src/Mono.Android/metadata` until `Mono.Android.csproj` builds - Check that new package/namespaces are properly cased +### New AndroidManifest.xml Elements + +- See `build-tools/manifest-attribute-codegen/README.md` for instructions on surfacing any new + elements or attributes added to `AndroidManifest.xml`. + ### ApiCompat There may be ApiCompat issues that need to be examined. Either fix the assembly with metadata or allow diff --git a/build-tools/manifest-attribute-codegen/Extensions/StringExtensions.cs b/build-tools/manifest-attribute-codegen/Extensions/StringExtensions.cs index 254a5fc4f07..bc075c6e48d 100644 --- a/build-tools/manifest-attribute-codegen/Extensions/StringExtensions.cs +++ b/build-tools/manifest-attribute-codegen/Extensions/StringExtensions.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using System.Text; using System.Xml.Linq; using Xamarin.SourceWriter; @@ -41,19 +42,6 @@ public static string ToActualName (this string s) return ret.Length == 0 ? "manifest" : ret; } - public static bool? GetAsBoolOrNull (this XElement element, string attribute) - { - var value = element.Attribute (attribute)?.Value; - - if (value is null) - return null; - - if (bool.TryParse (value, out var ret)) - return ret; - - return null; - } - public static bool GetAttributeBoolOrDefault (this XElement element, string attribute, bool defaultValue) { var value = element.Attribute (attribute)?.Value; @@ -117,4 +105,38 @@ public static void WriteAutoGeneratedHeader (this CodeWriter sw) sw.WriteLine (); sw.WriteLine ("#nullable enable"); // Roslyn turns off NRT for generated files by default, re-enable it } + + /// + /// Returns the first subset of a delimited string. ("127.0.0.1" -> "127") + /// + [return: NotNullIfNotNull (nameof (s))] + public static string? FirstSubset (this string? s, char separator) + { + if (!s.HasValue ()) + return s; + + var index = s.IndexOf (separator); + + if (index < 0) + return s; + + return s.Substring (0, index); + } + + /// + /// Returns the final subset of a delimited string. ("127.0.0.1" -> "1") + /// + [return: NotNullIfNotNull (nameof (s))] + public static string? LastSubset (this string? s, char separator) + { + if (!s.HasValue ()) + return s; + + var index = s.LastIndexOf (separator); + + if (index < 0) + return s; + + return s.Substring (index + 1); + } } diff --git a/build-tools/manifest-attribute-codegen/Models/AttributeDefinition.cs b/build-tools/manifest-attribute-codegen/Models/AttributeDefinition.cs index 3e3183021a3..369b1561821 100644 --- a/build-tools/manifest-attribute-codegen/Models/AttributeDefinition.cs +++ b/build-tools/manifest-attribute-codegen/Models/AttributeDefinition.cs @@ -17,6 +17,16 @@ public AttributeDefinition (string apiLevel, string name, string format) Format = format; } + public string GetAttributeType () + { + return Format switch { + "boolean" => "bool", + "integer" => "int", + "string" => "string?", + _ => "string?", + }; + } + public static AttributeDefinition FromElement (string api, XElement e) { var name = e.GetAttributeStringOrEmpty ("name"); diff --git a/build-tools/manifest-attribute-codegen/Models/MetadataSource.cs b/build-tools/manifest-attribute-codegen/Models/MetadataSource.cs index b830d53be9f..e28a912f476 100644 --- a/build-tools/manifest-attribute-codegen/Models/MetadataSource.cs +++ b/build-tools/manifest-attribute-codegen/Models/MetadataSource.cs @@ -5,26 +5,16 @@ namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; class MetadataSource { - public Dictionary Types { get; } = new (); - public Dictionary Elements { get; } = new (); - - static readonly MetadataElement default_element = new MetadataElement ("*"); - + public Dictionary Types { get; } = []; + public Dictionary Elements { get; } = []; public MetadataSource (string filename) { var xml = XElement.Load (filename); foreach (var element in xml.Elements ("element")) { - var path = element.Attribute ("path")?.Value ?? throw new InvalidDataException ("Missing 'path' attribute."); - - Elements.Add (path, new MetadataElement (path) { - Visible = element.GetAsBoolOrNull ("visible"), - Type = element.Attribute ("type")?.Value, - Name = element.Attribute ("name")?.Value, - Obsolete = element.Attribute ("obsolete")?.Value, - ReadOnly = element.GetAsBoolOrNull ("readonly") ?? false, - }); + var me = new MetadataAttribute (element); + Elements.Add (me.Path, me); } foreach (var element in xml.Elements ("type")) { @@ -33,83 +23,115 @@ public MetadataSource (string filename) } } - public MetadataElement GetMetadata (string path) + public MetadataAttribute GetMetadata (string path) { - if (Elements.TryGetValue (path, out var element)) { - element.Consumed = true; + if (Elements.TryGetValue (path, out var element)) return element; - } - return default_element; + throw new InvalidOperationException ($"No MetadataElement found for path '{path}'."); } - public void EnsureMetadataElementsConsumed () + public void EnsureAllElementsAccountedFor (List elements) { - var unconsumed = Elements.Values.Where (e => !e.Consumed).ToList (); - - if (unconsumed.Count == 0) - return; + var missing = new List (); - var sb = new StringBuilder (); - sb.AppendLine ("The following metadata elements were not consumed:"); + foreach (var e in elements) { + if (!Types.TryGetValue (e.ActualElementName, out var t)) { + missing.Add ($"- Type: <{e.ActualElementName}>"); + continue; + } - foreach (var e in unconsumed) - sb.AppendLine ($"- {e.Path}"); + if (t.Ignore) + continue; - throw new InvalidOperationException (sb.ToString ()); - } + foreach (var a in e.Attributes) { + var name = $"{e.ActualElementName}.{a.Name}"; - public void EnsureMetadataTypesConsumed () - { - var unconsumed = Types.Values.Where (t => !t.Consumed && !t.Ignore).ToList (); + if (!Elements.TryGetValue (name, out _)) + missing.Add ($"- Element: {name}"); + } + } - if (unconsumed.Count == 0) + if (missing.Count == 0) return; var sb = new StringBuilder (); - sb.AppendLine ("The following metadata types were not consumed:"); + sb.AppendLine ("The following manifest elements are not specified in the metadata:"); - foreach (var t in unconsumed) - sb.AppendLine ($"- {t.Name}"); + foreach (var m in missing) + sb.AppendLine (m); throw new InvalidOperationException (sb.ToString ()); } - public void EnsureAllTypesAccountedFor (IEnumerable elements) + public void EnsureAllMetadataElementsExistInManifest (List elements) { var missing = new List (); - foreach (var e in elements) { - if (!Types.ContainsKey (e.ActualElementName)) - missing.Add (e.ActualElementName); + foreach (var type in Types) { + var type_def = elements.FirstOrDefault (e => e.ActualElementName == type.Key); + + if (type_def is null) { + missing.Add ($"- Type: {type.Key}"); + continue; + } + } + + foreach (var type in Elements) { + var type_name = type.Key.FirstSubset ('.'); + var elem_name = type.Key.LastSubset ('.'); + + var type_def = elements.FirstOrDefault (e => e.ActualElementName == type_name); + + if (type_def is null) { + missing.Add ($"- Element: {type.Key}"); + continue; + } + + var elem_def = type_def.Attributes.FirstOrDefault (e => e.Name == elem_name); + + if (elem_def is null) { + missing.Add ($"- Element: {type.Key}"); + continue; + } } if (missing.Count == 0) return; var sb = new StringBuilder (); - sb.AppendLine ("The following types were not accounted for:"); + sb.AppendLine ("The following elements specified in the metadata were not found in the manifest:"); - foreach (var m in missing.Order ()) - sb.AppendLine ($"- {m}"); + foreach (var e in missing) + sb.AppendLine (e); throw new InvalidOperationException (sb.ToString ()); } } -class MetadataElement +class MetadataAttribute { public string Path { get; set; } - public bool? Visible { get; set; } + public bool Visible { get; set; } = true; public string? Type { get; set; } public string? Name { get; set; } public string? Obsolete { get; set; } public bool ReadOnly { get; set; } - public bool Consumed { get; set; } + public bool ManualMap { get; set; } - public MetadataElement (string path) + public MetadataAttribute (XElement element) { - Path = path; + Path = element.Attribute ("path")?.Value ?? throw new InvalidDataException ("Missing 'path' attribute."); + + if (!Path.Contains ('.')) + throw new InvalidDataException ($"Invalid 'path' attribute value: {Path}"); + + Visible = element.GetAttributeBoolOrDefault ("visible", true); + Type = element.Attribute ("type")?.Value; + Name = element.Attribute ("name")?.Value; + Obsolete = element.Attribute ("obsolete")?.Value; + ReadOnly = element.GetAttributeBoolOrDefault ("readonly", false); + ManualMap = element.GetAttributeBoolOrDefault ("manualMap", false); } } @@ -125,8 +147,7 @@ public class MetadataType public bool IsJniNameProvider { get; set; } public bool HasDefaultConstructor { get; set; } public bool IsSealed { get; set; } - public bool Consumed { get; set; } - + public bool GenerateMapping { get; set; } public MetadataType (XElement element) { @@ -141,8 +162,9 @@ public MetadataType (XElement element) Usage = element.GetRequiredAttributeString ("usage"); AllowMultiple = element.GetAttributeBoolOrDefault ("allowMultiple", false); IsJniNameProvider = element.GetAttributeBoolOrDefault ("jniNameProvider", false); - HasDefaultConstructor = element.GetAttributeBoolOrDefault("defaultConstructor", true); + HasDefaultConstructor = element.GetAttributeBoolOrDefault ("defaultConstructor", true); IsSealed = element.GetAttributeBoolOrDefault ("sealed", true); - ManagedName = element.Attribute ("managedName")?.Value ?? Name.Unhyphenate ().Capitalize () + "Attribute"; + ManagedName = element.Attribute ("managedName")?.Value ?? Name.Unhyphenate ().Capitalize () + "Attribute"; + GenerateMapping = element.GetAttributeBoolOrDefault ("generateMapping", true); } } diff --git a/build-tools/manifest-attribute-codegen/Program.cs b/build-tools/manifest-attribute-codegen/Program.cs index 1eb5be95954..17f28e4aa6a 100644 --- a/build-tools/manifest-attribute-codegen/Program.cs +++ b/build-tools/manifest-attribute-codegen/Program.cs @@ -74,6 +74,13 @@ public static int Main (string [] args) // Read metadata file var metadata = new MetadataSource (metadata_file); + // Ensure everything in the Android SDK is accounted for. + // This forces us to handle anything new that's been added to the SDK. + metadata.EnsureAllElementsAccountedFor (merged.Elements); + + // Ensure there are no unused elements in the metadata file + metadata.EnsureAllMetadataElementsExistInManifest (merged.Elements); + // Generate manifest attributes C# code foreach (var type in metadata.Types.Values.Where (t => !t.Ignore)) { using var w = new StreamWriter (Path.Combine (base_dir, type.OutputFile)); @@ -83,13 +90,6 @@ public static int Main (string [] args) writer.Write (cw); } - // Ensure everything we found in the Android SDK is accounted for. - // This forces us to handle anything new that's been added to the SDK. - // metadata.EnsureAllTypesExist (merged.Elements); - metadata.EnsureAllTypesAccountedFor (merged.Elements); - metadata.EnsureMetadataTypesConsumed (); - metadata.EnsureMetadataElementsConsumed (); - return 0; } } diff --git a/build-tools/manifest-attribute-codegen/README.md b/build-tools/manifest-attribute-codegen/README.md index fb675232512..e0122729ff0 100644 --- a/build-tools/manifest-attribute-codegen/README.md +++ b/build-tools/manifest-attribute-codegen/README.md @@ -1,11 +1,105 @@ # What is this? -manifest-attribute-codegen.exe is a simple tool that collects Android SDK -resource information about AndroidManifest.xml, then generate a unified +`manifest-attribute-codegen` a tool that collects Android SDK +resource information about what XML elements can be placed in an AndroidManifest.xml, then generate a unified element/attribute definition with "which API introduced this" information. -With that, we can find what needs to be added to xamarin-android. +Using this information, we can generate `[(Application|Activity|etc)Attribute]` classes that can be used +by both `Mono.Android` and `Xamarin.Android.Build.Tasks`. + +This generally only needs to be done each time we bind a new Android API level. + +# How to use + +Ensure all Android platform SDK levels are installed. This can be done with `xaprepare`: + +``` +xaprepare android-sdk-platforms=all +``` + +From this directory, run: + +``` +dotnet build -t:GenerateManifestAttributes +``` + +If all found elements/attributes are accounted for in `metadata.xml`, new `*Attribute.cs` files +will be generated. + +If everything isn't accounted for, you will be required to specify how to handle the new pieces. + +# Handling new types (elements) + +When a new type (element) like `` or `` is found, there are 2 choices: +ignore it or bind it. + +## Ignore the type + +The majority of the found types are not bound so the most likely scenario may be to ignore the new type: + +```xml + +``` + +## Bind the type + +Alternatively, the type can be bound: + +```xml + +``` + +Required metadata: + +- **name** - The name of the new element in AndroidManifest.xml, like `activity` or `application` +- **namespace** - The C# namespace the element will be placed in +- **outputFile** - The path to write the generated .cs +- **usage** - The `validOn` attribute usage information passed to `[AttributeUsage]` + +Optional metadata: + +- **allowMultiple** - The `allowMultiple` attribute usage information passed to `[AttributeUsage]`, defaults to `false` +- **jniNameProvider** - Whether the attribute should implement `Java.Interop.IJniNameProviderAttribute`, defaults to `false` +- **defaultConstructor** - Whether a parameterless constructor should be generated, defaults to `true` +- **sealed** - Whether the attribute type should be `sealed`, defaults to `true` +- **managedName** - The name of the managed attribute class if the default isn't correct +- **generateMapping** - Whether to generate the `mapping` field used by `Xamarin.Android.Build.Tasks, defaults to `true` + +Note that if a new type is created, there will be additional manual code that needs to written to configure +`Xamarin.Android.Build.Tasks` to translate the attribute to AndroidManifest xml. + +Example: + + - src/Xamarin.Android.Build.Tasks/Mono.Android/ApplicationAttribute.Partial.cs + - src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs + +# Handling new attributes + +When a new attribute like `` is added, it also must be specified if the attribute should be visible to users or not. + +## Hide the attribute + +To hide the attribute: + +```xml + +``` + +## Surface the attribute + +To surface the attribute: + +```xml + +``` + +Optional metadata (note that if any metadata is set, `visible` is assumed to be `true` unless specified otherwise): + +- **type** - C# type to override missing type information from the manifest definition +- **name** - The name of the managed attribute property if the default isn't correct +- **obsolete** - A string describing the reason for this member being `[Obsolete ("foo")]` +- **readonly** - Whether to generate the property with a `private set`, defaults to `false` +- **manualMap** - Whether to exclude the property from the `mapping` field used by `Xamarin.Android.Build.Tasks, defaults to `false` -(Note that this tools is not for generating code, at least for now.) diff --git a/build-tools/manifest-attribute-codegen/SourceWriters/AttributeDataClass.cs b/build-tools/manifest-attribute-codegen/SourceWriters/AttributeDataClass.cs index 50374eb674b..54b1f10825e 100644 --- a/build-tools/manifest-attribute-codegen/SourceWriters/AttributeDataClass.cs +++ b/build-tools/manifest-attribute-codegen/SourceWriters/AttributeDataClass.cs @@ -5,6 +5,11 @@ namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; // This is the common data class used by both Mono.Android and Xamarin.Android.Build.Tasks. class AttributeDataClass : ClassWriter { + AttributeMappingField? mapping_field; + AttributeMappingStaticConstructor? static_constructor; + + static AttributeMappingManualInitializer manual_mapping_partial = AttributeMappingManualInitializer.Create (); + public string Namespace { get; set; } public AttributeDataClass (string ns) @@ -14,8 +19,6 @@ public AttributeDataClass (string ns) public static AttributeDataClass Create (ElementDefinition attr, MetadataSource metadata, MetadataType type) { - type.Consumed = true; - var c = new AttributeDataClass (type.Namespace) { Name = type.ManagedName, IsPublic = true, @@ -41,12 +44,12 @@ public static AttributeDataClass Create (ElementDefinition attr, MetadataSource foreach (var a in attr.Attributes.OrderBy (a => a.Name)) { var attr_metadata = metadata.GetMetadata ($"{attr.ActualElementName}.{a.Name}"); - if (attr_metadata.Visible == false) + if (!attr_metadata.Visible) continue; var p = new PropertyWriter { Name = (attr_metadata.Name ?? a.Name).Capitalize (), - PropertyType = new TypeReferenceWriter (attr_metadata.Type ?? GetAttributeType (a)), + PropertyType = new TypeReferenceWriter (attr_metadata.Type ?? a.GetAttributeType ()), IsPublic = true, HasGet = true, HasSet = true, @@ -61,17 +64,13 @@ public static AttributeDataClass Create (ElementDefinition attr, MetadataSource c.Properties.Add (p); } - return c; - } + // Create mapping field used by Xamarin.Android.Build.Tasks + if (type.GenerateMapping) { + c.mapping_field = AttributeMappingField.Create (type); + c.static_constructor = AttributeMappingStaticConstructor.Create (attr, metadata, type); + } - static string GetAttributeType (AttributeDefinition attr) - { - return attr.Format switch { - "boolean" => "bool", - "integer" => "int", - "string" => "string?", - _ => "string?", - }; + return c; } public override void Write (CodeWriter writer) @@ -86,4 +85,23 @@ public override void Write (CodeWriter writer) base.Write (writer); } + + public override void WriteMembers (CodeWriter writer) + { + base.WriteMembers (writer); + + if (mapping_field is not null) { + writer.WriteLineNoIndent ("#if XABT_MANIFEST_EXTENSIONS"); + + mapping_field?.Write (writer); + writer.WriteLine (); + + static_constructor?.Write (writer); + writer.WriteLine (); + + manual_mapping_partial?.Write (writer); + + writer.WriteLineNoIndent ("#endif"); + } + } } diff --git a/build-tools/manifest-attribute-codegen/SourceWriters/AttributeMappingField.cs b/build-tools/manifest-attribute-codegen/SourceWriters/AttributeMappingField.cs new file mode 100644 index 00000000000..1068c2ecad8 --- /dev/null +++ b/build-tools/manifest-attribute-codegen/SourceWriters/AttributeMappingField.cs @@ -0,0 +1,18 @@ +using Xamarin.SourceWriter; + +namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; + +class AttributeMappingField : FieldWriter +{ + public static AttributeMappingField Create (MetadataType type) + { + var field = new AttributeMappingField { + Name = "mapping", + IsStatic = true, + Type = new TypeReferenceWriter ($"Xamarin.Android.Manifest.ManifestDocumentElement<{type.ManagedName}>"), + Value = $"new (\"{type.Name}\")", + }; + + return field; + } +} diff --git a/build-tools/manifest-attribute-codegen/SourceWriters/AttributeMappingManualInitializer.cs b/build-tools/manifest-attribute-codegen/SourceWriters/AttributeMappingManualInitializer.cs new file mode 100644 index 00000000000..b1b2aa5032e --- /dev/null +++ b/build-tools/manifest-attribute-codegen/SourceWriters/AttributeMappingManualInitializer.cs @@ -0,0 +1,19 @@ +using Xamarin.SourceWriter; + +namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; + +class AttributeMappingManualInitializer : MethodWriter +{ + public static AttributeMappingManualInitializer Create () + { + var method = new AttributeMappingManualInitializer { + Name = "AddManualMapping", + IsStatic = true, + IsPartial = true, + IsDeclaration = true, + ReturnType = TypeReferenceWriter.Void, + }; + + return method; + } +} diff --git a/build-tools/manifest-attribute-codegen/SourceWriters/AttributeMappingStaticConstructor.cs b/build-tools/manifest-attribute-codegen/SourceWriters/AttributeMappingStaticConstructor.cs new file mode 100644 index 00000000000..9264c959940 --- /dev/null +++ b/build-tools/manifest-attribute-codegen/SourceWriters/AttributeMappingStaticConstructor.cs @@ -0,0 +1,45 @@ +using Xamarin.SourceWriter; + +namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator; + +class AttributeMappingStaticConstructor : ConstructorWriter +{ + public static AttributeMappingStaticConstructor Create (ElementDefinition attr, MetadataSource metadata, MetadataType type) + { + var ctor = new AttributeMappingStaticConstructor { + Name = type.ManagedName, + IsStatic = true, + }; + + // mapping.Add ( + // member: "Name", + // attributeName: "name", + // getter: self => self.Name, + // setter: (self, value) => self.Name = (string?) value + // ); + foreach (var a in attr.Attributes.OrderBy (a => a.Name)) { + var attr_metadata = metadata.GetMetadata ($"{attr.ActualElementName}.{a.Name}"); + + if (!attr_metadata.Visible || attr_metadata.ManualMap) + continue; + + var name = (attr_metadata.Name ?? a.Name).Capitalize (); + var setter = $"(self, value) => self.{name} = ({attr_metadata.Type ?? a.GetAttributeType ()}) value"; + + if (attr_metadata.ReadOnly) + setter = "null"; + + ctor.Body.Add ($"mapping.Add ("); + ctor.Body.Add ($" member: \"{name}\","); + ctor.Body.Add ($" attributeName: \"{a.Name}\","); + ctor.Body.Add ($" getter: self => self.{name},"); + ctor.Body.Add ($" setter: {setter}"); + ctor.Body.Add ($");"); + } + + ctor.Body.Add (string.Empty); + ctor.Body.Add ($"AddManualMapping ();"); + + return ctor; + } +} diff --git a/build-tools/manifest-attribute-codegen/metadata.xml b/build-tools/manifest-attribute-codegen/metadata.xml index 64baac1a7ca..4f0d7d3d4ad 100644 --- a/build-tools/manifest-attribute-codegen/metadata.xml +++ b/build-tools/manifest-attribute-codegen/metadata.xml @@ -6,21 +6,22 @@ - - + + - - - + + + + - + @@ -66,12 +67,11 @@ - - + @@ -80,39 +80,51 @@ + + + + + + + + + - + + + + @@ -122,6 +134,8 @@ + + @@ -139,14 +153,16 @@ + - + + @@ -156,31 +172,46 @@ + + + + - + + + + + + + + + + + + @@ -189,57 +220,92 @@ + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -247,22 +313,37 @@ + + + + + + + + - - + + + + + + + + + @@ -274,7 +355,14 @@ + + + + + + + @@ -284,13 +372,25 @@ + + + - + + + + + + + + + + \ No newline at end of file diff --git a/src/Mono.Android/Android.App/MetaDataAttribute.cs b/src/Mono.Android/Android.App/MetaDataAttribute.cs index 42794bac120..b1d758a89fe 100644 --- a/src/Mono.Android/Android.App/MetaDataAttribute.cs +++ b/src/Mono.Android/Android.App/MetaDataAttribute.cs @@ -22,4 +22,33 @@ public sealed partial class MetaDataAttribute : Attribute { public string? Value { get; set; } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("meta-data"); + + static MetaDataAttribute () + { + mapping.Add ( + member: "Name", + attributeName: "name", + getter: self => self.Name, + setter: null + ); + mapping.Add ( + member: "Resource", + attributeName: "resource", + getter: self => self.Resource, + setter: (self, value) => self.Resource = (string?) value + ); + mapping.Add ( + member: "Value", + attributeName: "value", + getter: self => self.Value, + setter: (self, value) => self.Value = (string?) value + ); + + AddManualMapping (); + } + + static partial void AddManualMapping (); +#endif } diff --git a/src/Mono.Android/Android.App/PermissionAttribute.cs b/src/Mono.Android/Android.App/PermissionAttribute.cs index 997ff852d16..b3aa4cf7e3a 100644 --- a/src/Mono.Android/Android.App/PermissionAttribute.cs +++ b/src/Mono.Android/Android.App/PermissionAttribute.cs @@ -34,4 +34,57 @@ public PermissionAttribute () public string? RoundIcon { get; set; } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("permission"); + + static PermissionAttribute () + { + mapping.Add ( + member: "Description", + attributeName: "description", + getter: self => self.Description, + setter: (self, value) => self.Description = (string?) value + ); + mapping.Add ( + member: "Icon", + attributeName: "icon", + getter: self => self.Icon, + setter: (self, value) => self.Icon = (string?) value + ); + mapping.Add ( + member: "Label", + attributeName: "label", + getter: self => self.Label, + setter: (self, value) => self.Label = (string?) value + ); + mapping.Add ( + member: "Name", + attributeName: "name", + getter: self => self.Name, + setter: (self, value) => self.Name = (string?) value + ); + mapping.Add ( + member: "PermissionGroup", + attributeName: "permissionGroup", + getter: self => self.PermissionGroup, + setter: (self, value) => self.PermissionGroup = (string?) value + ); + mapping.Add ( + member: "ProtectionLevel", + attributeName: "protectionLevel", + getter: self => self.ProtectionLevel, + setter: (self, value) => self.ProtectionLevel = (Android.Content.PM.Protection) value + ); + mapping.Add ( + member: "RoundIcon", + attributeName: "roundIcon", + getter: self => self.RoundIcon, + setter: (self, value) => self.RoundIcon = (string?) value + ); + + AddManualMapping (); + } + + static partial void AddManualMapping (); +#endif } diff --git a/src/Mono.Android/Android.App/PermissionGroupAttribute.cs b/src/Mono.Android/Android.App/PermissionGroupAttribute.cs index 41df8b07205..ff083697a01 100644 --- a/src/Mono.Android/Android.App/PermissionGroupAttribute.cs +++ b/src/Mono.Android/Android.App/PermissionGroupAttribute.cs @@ -30,4 +30,45 @@ public PermissionGroupAttribute () public string? RoundIcon { get; set; } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("permission-group"); + + static PermissionGroupAttribute () + { + mapping.Add ( + member: "Description", + attributeName: "description", + getter: self => self.Description, + setter: (self, value) => self.Description = (string?) value + ); + mapping.Add ( + member: "Icon", + attributeName: "icon", + getter: self => self.Icon, + setter: (self, value) => self.Icon = (string?) value + ); + mapping.Add ( + member: "Label", + attributeName: "label", + getter: self => self.Label, + setter: (self, value) => self.Label = (string?) value + ); + mapping.Add ( + member: "Name", + attributeName: "name", + getter: self => self.Name, + setter: (self, value) => self.Name = (string?) value + ); + mapping.Add ( + member: "RoundIcon", + attributeName: "roundIcon", + getter: self => self.RoundIcon, + setter: (self, value) => self.RoundIcon = (string?) value + ); + + AddManualMapping (); + } + + static partial void AddManualMapping (); +#endif } diff --git a/src/Mono.Android/Android.App/PermissionTreeAttribute.cs b/src/Mono.Android/Android.App/PermissionTreeAttribute.cs index 7134b1940ad..b36131bdd1a 100644 --- a/src/Mono.Android/Android.App/PermissionTreeAttribute.cs +++ b/src/Mono.Android/Android.App/PermissionTreeAttribute.cs @@ -28,4 +28,39 @@ public PermissionTreeAttribute () public string? RoundIcon { get; set; } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("permission-tree"); + + static PermissionTreeAttribute () + { + mapping.Add ( + member: "Icon", + attributeName: "icon", + getter: self => self.Icon, + setter: (self, value) => self.Icon = (string?) value + ); + mapping.Add ( + member: "Label", + attributeName: "label", + getter: self => self.Label, + setter: (self, value) => self.Label = (string?) value + ); + mapping.Add ( + member: "Name", + attributeName: "name", + getter: self => self.Name, + setter: (self, value) => self.Name = (string?) value + ); + mapping.Add ( + member: "RoundIcon", + attributeName: "roundIcon", + getter: self => self.RoundIcon, + setter: (self, value) => self.RoundIcon = (string?) value + ); + + AddManualMapping (); + } + + static partial void AddManualMapping (); +#endif } diff --git a/src/Mono.Android/Android.App/UsesConfigurationAttribute.cs b/src/Mono.Android/Android.App/UsesConfigurationAttribute.cs index 7e4b8da9564..27ff2116ba1 100644 --- a/src/Mono.Android/Android.App/UsesConfigurationAttribute.cs +++ b/src/Mono.Android/Android.App/UsesConfigurationAttribute.cs @@ -30,4 +30,45 @@ public UsesConfigurationAttribute () public string? ReqTouchScreen { get; set; } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("uses-configuration"); + + static UsesConfigurationAttribute () + { + mapping.Add ( + member: "ReqFiveWayNav", + attributeName: "reqFiveWayNav", + getter: self => self.ReqFiveWayNav, + setter: (self, value) => self.ReqFiveWayNav = (bool) value + ); + mapping.Add ( + member: "ReqHardKeyboard", + attributeName: "reqHardKeyboard", + getter: self => self.ReqHardKeyboard, + setter: (self, value) => self.ReqHardKeyboard = (bool) value + ); + mapping.Add ( + member: "ReqKeyboardType", + attributeName: "reqKeyboardType", + getter: self => self.ReqKeyboardType, + setter: (self, value) => self.ReqKeyboardType = (string?) value + ); + mapping.Add ( + member: "ReqNavigation", + attributeName: "reqNavigation", + getter: self => self.ReqNavigation, + setter: (self, value) => self.ReqNavigation = (string?) value + ); + mapping.Add ( + member: "ReqTouchScreen", + attributeName: "reqTouchScreen", + getter: self => self.ReqTouchScreen, + setter: (self, value) => self.ReqTouchScreen = (string?) value + ); + + AddManualMapping (); + } + + static partial void AddManualMapping (); +#endif } diff --git a/src/Mono.Android/Android.App/UsesFeatureAttribute.cs b/src/Mono.Android/Android.App/UsesFeatureAttribute.cs index 53f675e7485..848abd93aa9 100644 --- a/src/Mono.Android/Android.App/UsesFeatureAttribute.cs +++ b/src/Mono.Android/Android.App/UsesFeatureAttribute.cs @@ -28,4 +28,33 @@ public UsesFeatureAttribute () public int Version { get; private set; } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("uses-feature"); + + static UsesFeatureAttribute () + { + mapping.Add ( + member: "Name", + attributeName: "name", + getter: self => self.Name, + setter: null + ); + mapping.Add ( + member: "Required", + attributeName: "required", + getter: self => self.Required, + setter: (self, value) => self.Required = (bool) value + ); + mapping.Add ( + member: "Version", + attributeName: "version", + getter: self => self.Version, + setter: null + ); + + AddManualMapping (); + } + + static partial void AddManualMapping (); +#endif } diff --git a/src/Mono.Android/Android.App/UsesLibraryAttribute.cs b/src/Mono.Android/Android.App/UsesLibraryAttribute.cs index 22ad989714e..00361462c6c 100644 --- a/src/Mono.Android/Android.App/UsesLibraryAttribute.cs +++ b/src/Mono.Android/Android.App/UsesLibraryAttribute.cs @@ -24,4 +24,27 @@ public UsesLibraryAttribute () public bool Required { get; set; } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("uses-library"); + + static UsesLibraryAttribute () + { + mapping.Add ( + member: "Name", + attributeName: "name", + getter: self => self.Name, + setter: (self, value) => self.Name = (string?) value + ); + mapping.Add ( + member: "Required", + attributeName: "required", + getter: self => self.Required, + setter: (self, value) => self.Required = (bool) value + ); + + AddManualMapping (); + } + + static partial void AddManualMapping (); +#endif } diff --git a/src/Mono.Android/Android.App/UsesPermissionAttribute.Partial.cs b/src/Mono.Android/Android.App/UsesPermissionAttribute.Partial.cs new file mode 100644 index 00000000000..085d327bcde --- /dev/null +++ b/src/Mono.Android/Android.App/UsesPermissionAttribute.Partial.cs @@ -0,0 +1,9 @@ +namespace Android.App; + +public sealed partial class UsesPermissionAttribute +{ + public UsesPermissionAttribute (string name) + { + Name = name; + } +} diff --git a/src/Mono.Android/Android.App/UsesPermissionAttribute.cs b/src/Mono.Android/Android.App/UsesPermissionAttribute.cs index cf2e0fd49ec..62cc0f433ad 100644 --- a/src/Mono.Android/Android.App/UsesPermissionAttribute.cs +++ b/src/Mono.Android/Android.App/UsesPermissionAttribute.cs @@ -1,28 +1,50 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by 'manifest-attribute-codegen'. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + using System; -using Android.Content.PM; -using Android.Views; +namespace Android.App; -namespace Android.App { +[Serializable] +[AttributeUsage (AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] +public sealed partial class UsesPermissionAttribute : Attribute { + public UsesPermissionAttribute () + { + } - [Serializable] - [AttributeUsage (AttributeTargets.Assembly, - AllowMultiple=true, - Inherited=false)] - public sealed partial class UsesPermissionAttribute : Attribute { + public int MaxSdkVersion { get; set; } - public UsesPermissionAttribute () - { - } + public string? Name { get; set; } - public UsesPermissionAttribute (string name) - { - Name = name; - } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("uses-permission"); - public string? Name {get; set;} -#if ANDROID_19 - public int MaxSdkVersion {get; set;} -#endif + static UsesPermissionAttribute () + { + mapping.Add ( + member: "MaxSdkVersion", + attributeName: "maxSdkVersion", + getter: self => self.MaxSdkVersion, + setter: (self, value) => self.MaxSdkVersion = (int) value + ); + mapping.Add ( + member: "Name", + attributeName: "name", + getter: self => self.Name, + setter: (self, value) => self.Name = (string?) value + ); + + AddManualMapping (); } + + static partial void AddManualMapping (); +#endif } diff --git a/src/Mono.Android/Android.Content/GrantUriPermissionAttribute.cs b/src/Mono.Android/Android.Content/GrantUriPermissionAttribute.cs index 2fc2f219e5b..7185a789031 100644 --- a/src/Mono.Android/Android.Content/GrantUriPermissionAttribute.cs +++ b/src/Mono.Android/Android.Content/GrantUriPermissionAttribute.cs @@ -26,4 +26,33 @@ public GrantUriPermissionAttribute () public string? PathPrefix { get; set; } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("grant-uri-permission"); + + static GrantUriPermissionAttribute () + { + mapping.Add ( + member: "Path", + attributeName: "path", + getter: self => self.Path, + setter: (self, value) => self.Path = (string?) value + ); + mapping.Add ( + member: "PathPattern", + attributeName: "pathPattern", + getter: self => self.PathPattern, + setter: (self, value) => self.PathPattern = (string?) value + ); + mapping.Add ( + member: "PathPrefix", + attributeName: "pathPrefix", + getter: self => self.PathPrefix, + setter: (self, value) => self.PathPrefix = (string?) value + ); + + AddManualMapping (); + } + + static partial void AddManualMapping (); +#endif } diff --git a/src/Mono.Android/Mono.Android.csproj b/src/Mono.Android/Mono.Android.csproj index 202ebb04b7e..1a246e78183 100644 --- a/src/Mono.Android/Mono.Android.csproj +++ b/src/Mono.Android/Mono.Android.csproj @@ -83,6 +83,7 @@ + diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/ActivityAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/ActivityAttribute.Partial.cs index bcf3cbac190..580ddc60f04 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/ActivityAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/ActivityAttribute.Partial.cs @@ -16,324 +16,27 @@ namespace Android.App { partial class ActivityAttribute { - bool _AllowEmbedded; - bool _AutoRemoveFromRecents; - string _Banner; - string _ColorMode; - DocumentLaunchMode _DocumentLaunchMode; - bool _HardwareAccelerated; - bool _Immersive; - LayoutDirection _LayoutDirection; - string _LockTaskMode; - string _Logo; - float _MaxAspectRatio; - int _MaxRecents; string _ParentActivity; - ActivityPersistableMode _PersistableMode; - ConfigChanges _RecreateOnConfigChanges; - bool _RelinquishTaskIdentity; - bool _ResizeableActivity; - bool _ResumeWhilePausing; - WindowRotationAnimation _RotationAnimation; - string _RoundIcon; - bool _ShowForAllUsers; - bool _ShowOnLockScreen; - bool _ShowWhenLocked; - bool _SingleUser; - bool _SupportsPictureInPicture; - bool _TurnScreenOn; - UiOptions _UiOptions; - bool _VisibleToInstantApps; - - static ManifestDocumentElement mapping = new ManifestDocumentElement ("activity") { - { - "AllowEmbedded", - "allowEmbedded", - self => self._AllowEmbedded, - (self, value) => self._AllowEmbedded = (bool) value - }, { - "AllowTaskReparenting", - "allowTaskReparenting", - self => self.AllowTaskReparenting, - (self, value) => self.AllowTaskReparenting = (bool) value - }, { - "AlwaysRetainTaskState", - "alwaysRetainTaskState", - self => self.AlwaysRetainTaskState, - (self, value) => self.AlwaysRetainTaskState = (bool) value - }, { - "AutoRemoveFromRecents", - "autoRemoveFromRecents", - self => self._AutoRemoveFromRecents, - (self, value) => self._AutoRemoveFromRecents = (bool) value - }, { - "Banner", - "banner", - self => self._Banner, - (self, value) => self._Banner = (string) value - }, { - "ClearTaskOnLaunch", - "clearTaskOnLaunch", - self => self.ClearTaskOnLaunch, - (self, value) => self.ClearTaskOnLaunch = (bool) value - }, { - "ColorMode", - "colorMode", - self => self._ColorMode, - (self, value) => self._ColorMode = (string) value - }, { - "ConfigurationChanges", - "configChanges", - self => self.ConfigurationChanges, - (self, value) => self.ConfigurationChanges = (ConfigChanges) value - }, { - // TODO: Not currently documented at: https://developer.android.com/guide/topics/manifest/activity-element - "Description", - "description", - self => self.Description, - (self, value) => self.Description = (string) value - }, { - "DirectBootAware", - "directBootAware", - self => self.DirectBootAware, - (self, value) => self.DirectBootAware = (bool) value - }, { - "DocumentLaunchMode", - "documentLaunchMode", - self => self._DocumentLaunchMode, - (self, value) => self._DocumentLaunchMode = (DocumentLaunchMode) value - }, { - "Enabled", - "enabled", - self => self.Enabled, - (self, value) => self.Enabled = (bool) value - }, { - // TODO: Not currently documented at: https://developer.android.com/guide/topics/manifest/activity-element - "EnableVrMode", - "enableVrMode", - self => self.EnableVrMode, - (self, value) => self.EnableVrMode = (string) value - }, { - "ExcludeFromRecents", - "excludeFromRecents", - self => self.ExcludeFromRecents, - (self, value) => self.ExcludeFromRecents = (bool) value - }, { - "Exported", - "exported", - self => self.Exported, - (self, value) => self.Exported = (bool) value - }, { - // TODO: Not currently documented at: https://developer.android.com/guide/topics/manifest/activity-element - "FinishOnCloseSystemDialogs", - "finishOnCloseSystemDialogs", - self => self.FinishOnCloseSystemDialogs, - (self, value) => self.FinishOnCloseSystemDialogs = (bool) value - }, { - "FinishOnTaskLaunch", - "finishOnTaskLaunch", - self => self.FinishOnTaskLaunch, - (self, value) => self.FinishOnTaskLaunch = (bool) value - }, { - "HardwareAccelerated", - "hardwareAccelerated", - self => self._HardwareAccelerated, - (self, value) => self._HardwareAccelerated = (bool) value - }, { - "Icon", - "icon", - self => self.Icon, - (self, value) => self.Icon = (string) value - }, { - "Immersive", - "immersive", - self => self._Immersive, - (self, value) => self._Immersive = (bool) value - }, { - "Label", - "label", - self => self.Label, - (self, value) => self.Label = (string) value - }, { - "LaunchMode", - "launchMode", - self => self.LaunchMode, - (self, value) => self.LaunchMode = (LaunchMode) value - }, { - // TODO: Not currently documented at: https://developer.android.com/guide/topics/manifest/activity-element - "LayoutDirection", - "layoutDirection", - self => self._LayoutDirection, - (self, value) => self._LayoutDirection = (LayoutDirection) value - }, { - // TODO: Not currently documented at: https://developer.android.com/guide/topics/manifest/activity-element - "LockTaskMode", - "lockTaskMode", - self => self._LockTaskMode, - (self, value) => self._LockTaskMode = (string) value - }, { - "Logo", - "logo", - self => self._Logo, - (self, value) => self._Logo = (string) value - }, { - "MainLauncher", - null, - null, - (self, value) => self.MainLauncher = (bool) value - }, { - "MaxAspectRatio", - "maxAspectRatio", - self => self._MaxAspectRatio, - (self, value) => self._MaxAspectRatio = (float) value - }, { - "MaxRecents", - "maxRecents", - self => self._MaxRecents, - (self, value) => self._MaxRecents = (int) value - }, { - "MultiProcess", - "multiprocess", - self => self.MultiProcess, - (self, value) => self.MultiProcess = (bool) value - }, { - "Name", - "name", - self => self.Name, - (self, value) => self.Name = (string) value - }, { - "NoHistory", - "noHistory", - self => self.NoHistory, - (self, value) => self.NoHistory = (bool) value - }, { - "ParentActivity", - "parentActivityName", - self => self._ParentActivity, - (self, value) => self._ParentActivity = (string) value, - typeof (Type) - }, { - "Permission", - "permission", - self => self.Permission, - (self, value) => self.Permission = (string) value - }, { - "PersistableMode", - "persistableMode", - self => self._PersistableMode, - (self, value) => self._PersistableMode = (ActivityPersistableMode) value - }, { - "Process", - "process", - self => self.Process, - (self, value) => self.Process = (string) value - }, { - // TODO: Not currently documented at: https://developer.android.com/guide/topics/manifest/activity-element - "RecreateOnConfigChanges", - "recreateOnConfigChanges", - self => self._RecreateOnConfigChanges, - (self, value) => self._RecreateOnConfigChanges = (ConfigChanges) value - }, { - "RelinquishTaskIdentity", - "relinquishTaskIdentity", - self => self._RelinquishTaskIdentity, - (self, value) => self._RelinquishTaskIdentity = (bool) value - }, { - "ResizeableActivity", - "resizeableActivity", - self => self._ResizeableActivity, - (self, value) => self._ResizeableActivity = (bool) value - }, { - "ResumeWhilePausing", - "resumeWhilePausing", - self => self._ResumeWhilePausing, - (self, value) => self._ResumeWhilePausing = (bool) value - }, { - // TODO: Not currently documented at: https://developer.android.com/guide/topics/manifest/activity-element - "RotationAnimation", - "rotationAnimation", - self => self._RotationAnimation, - (self, value) => self._RotationAnimation = (WindowRotationAnimation) value - }, { - "RoundIcon", - "roundIcon", - self => self._RoundIcon, - (self, value) => self._RoundIcon = (string) value - }, { - "ScreenOrientation", - "screenOrientation", - self => self.ScreenOrientation, - (self, value) => self.ScreenOrientation = (ScreenOrientation) value - }, { - "ShowForAllUsers", - "showForAllUsers", - self => self._ShowForAllUsers, - (self, value) => self._ShowForAllUsers = (bool) value - }, { - "ShowOnLockScreen", - "showOnLockScreen", - self => self._ShowOnLockScreen, - (self, value) => self._ShowOnLockScreen = (bool) value - }, { - // TODO: Not currently documented at: https://developer.android.com/guide/topics/manifest/activity-element - "ShowWhenLocked", - "showWhenLocked", - self => self._ShowWhenLocked, - (self, value) => self._ShowWhenLocked = (bool) value - }, { - // TODO: Not currently documented at: https://developer.android.com/guide/topics/manifest/activity-element - "SingleUser", - "singleUser", - self => self._SingleUser, - (self, value) => self._SingleUser = (bool) value - }, { - "StateNotNeeded", - "stateNotNeeded", - self => self.StateNotNeeded, - (self, value) => self.StateNotNeeded = (bool) value - }, { - "SupportsPictureInPicture", - "supportsPictureInPicture", - self => self._SupportsPictureInPicture, - (self, value) => self._SupportsPictureInPicture = (bool) value - }, { - "TaskAffinity", - "taskAffinity", - self => self.TaskAffinity, - (self, value) => self.TaskAffinity = (string) value - }, { - "Theme", - "theme", - self => self.Theme, - (self, value) => self.Theme = (string) value - }, { - // TODO: Not currently documented at: https://developer.android.com/guide/topics/manifest/activity-element - "TurnScreenOn", - "turnScreenOn", - self => self._TurnScreenOn, - (self, value) => self._TurnScreenOn = (bool) value - }, { - "UiOptions", - "uiOptions", - self => self._UiOptions, - (self, value) => self._UiOptions = (UiOptions) value - }, { - // TODO: Not currently documented at: https://developer.android.com/guide/topics/manifest/activity-element - "VisibleToInstantApps", - "visibleToInstantApps", - self => self._VisibleToInstantApps, - (self, value) => self._VisibleToInstantApps = (bool) value - }, { - "WindowSoftInputMode", - "windowSoftInputMode", - self => self.WindowSoftInputMode, - (self, value) => self.WindowSoftInputMode = (SoftInput) value - }, - }; - TypeDefinition type; ICollection specified; + static partial void AddManualMapping () + { + mapping.Add ( + member: "MainLauncher", + attributeName: null, + getter: null, + setter: (self, value) => self.MainLauncher = (bool) value + ); + mapping.Add ( + member: "ParentActivity", + attributeName: "parentActivityName", + getter: self => self._ParentActivity, + setter: (self, value) => self._ParentActivity = (string) value, + typeof (Type) + ); + } + public static ActivityAttribute FromTypeDefinition (TypeDefinition type, TypeDefinitionCache cache) { CustomAttribute attr = type.GetCustomAttributes ("Android.App.ActivityAttribute") diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/ApplicationAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/ApplicationAttribute.Partial.cs index 36a9dd867d2..4507424b7a5 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/ApplicationAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/ApplicationAttribute.Partial.cs @@ -19,47 +19,17 @@ namespace Android.App { partial class ApplicationAttribute { string _BackupAgent; - bool _BackupInForeground; - string _Banner; - bool _FullBackupOnly; - string _Logo; - string _ManageSpaceActivity; - string _NetworkSecurityConfig; - string _RequiredAccountType; - string _RestrictedAccountType; - bool _HardwareAccelerated; - bool _ExtractNativeLibs; - bool _FullBackupContent; - bool _LargeHeap; - UiOptions _UiOptions; - bool _SupportsRtl; - bool _UsesCleartextTraffic; - bool _VMSafeMode; - bool _ResizeableActivity; ICustomAttributeProvider provider; - string _RoundIcon; - static ManifestDocumentElement mapping = new ManifestDocumentElement ("application") { - { - "AllowBackup", - "allowBackup", - self => self.AllowBackup, - (self, value) => self.AllowBackup = (bool) value - }, { - "AllowClearUserData", - "allowClearUserData", - self => self.AllowClearUserData, - (self, value) => self.AllowClearUserData = (bool) value - }, { - "AllowTaskReparenting", - "allowTaskReparenting", - self => self.AllowTaskReparenting, - (self, value) => self.AllowTaskReparenting = (bool) value - }, { - "BackupAgent", - "backupAgent", - (self, value) => self._BackupAgent = (string) value, - (self, p, r, cache) => { + ICollection specified; + + static partial void AddManualMapping () + { + mapping.Add ( + member: "BackupAgent", + attributeName: "backupAgent", + setter: (self, value) => self._BackupAgent = (string) value, + attributeValue: (self, p, r, cache) => { var typeDef = ManifestDocumentElement.ResolveType (self._BackupAgent, p, r); if (!typeDef.IsSubclassOf ("Android.App.Backup.BackupAgent", cache)) @@ -68,177 +38,22 @@ partial class ApplicationAttribute { typeDef.FullName)); return ManifestDocumentElement.ToString (typeDef, cache); - } - }, { - "BackupInForeground", - "backupInForeground", - self => self._BackupInForeground, - (self, value) => self._BackupInForeground = (bool) value - }, { - "Banner", - "banner", - self => self._Banner, - (self, value) => self._Banner = (string) value - }, { - "Debuggable", - "debuggable", - self => self.Debuggable, - (self, value) => self.Debuggable = (bool) value - }, { - "Description", - "description", - self => self.Description, - (self, value) => self.Description = (string) value - }, { - "DirectBootAware", - "directBootAware", - self => self.DirectBootAware, - (self, value) => self.DirectBootAware = (bool) value - }, { - "Enabled", - "enabled", - self => self.Enabled, - (self, value) => self.Enabled = (bool) value - }, { - "ExtractNativeLibs", - "extractNativeLibs", - self => self._ExtractNativeLibs, - (self, value) => self._ExtractNativeLibs = (bool) value - }, { - "FullBackupContent", - "fullBackupContent", - self => self._FullBackupContent, - (self, value) => self._FullBackupContent = (bool) value - }, { - "FullBackupOnly", - "fullBackupOnly", - self => self._FullBackupOnly, - (self, value) => self._FullBackupOnly = (bool) value - }, { - "HardwareAccelerated", - "hardwareAccelerated", - self => self._HardwareAccelerated, - (self, value) => self._HardwareAccelerated = (bool) value - }, { - "HasCode", - "hasCode", - self => self.HasCode, - (self, value) => self.HasCode = (bool) value - }, { - "Icon", - "icon", - self => self.Icon, - (self, value) => self.Icon = (string) value - }, { - "KillAfterRestore", - "killAfterRestore", - self => self.KillAfterRestore, - (self, value) => self.KillAfterRestore = (bool) value - }, { - "Label", - "label", - self => self.Label, - (self, value) => self.Label = (string) value - }, { - "LargeHeap", - "largeHeap", - self => self._LargeHeap, - (self, value) => self._LargeHeap = (bool) value - }, { - "Logo", - "logo", - self => self._Logo, - (self, value) => self._Logo = (string) value - }, { - "ManageSpaceActivity", - "manageSpaceActivity", - self => self._ManageSpaceActivity, - (self, value) => self._ManageSpaceActivity = (string) value, - typeof (Type) - }, { - "Name", - "name", - (self, value) => self.Name = (string) value, - ToNameAttribute - }, { - "NetworkSecurityConfig", - "networkSecurityConfig", - self => self._NetworkSecurityConfig, - (self, value) => self._NetworkSecurityConfig = (string) value - }, { - "Permission", - "permission", - self => self.Permission, - (self, value) => self.Permission = (string) value - }, { - "Persistent", - "persistent", - self => self.Persistent, - (self, value) => self.Persistent = (bool) value - }, { - "Process", - "process", - self => self.Process, - (self, value) => self.Process = (string) value - }, { - "ResizeableActivity", - "resizeableActivity", - self => self._ResizeableActivity, - (self, value) => self._ResizeableActivity = (bool) value - }, { - "RequiredAccountType", - "requiredAccountType", - self => self._RequiredAccountType, - (self, value) => self._RequiredAccountType = (string) value - }, { - "RestoreAnyVersion", - "restoreAnyVersion", - self => self.RestoreAnyVersion, - (self, value) => self.RestoreAnyVersion = (bool) value - }, { - "RestrictedAccountType", - "restrictedAccountType", - self => self._RestrictedAccountType, - (self, value) => self._RestrictedAccountType = (string) value - }, { - "RoundIcon", - "roundIcon", - self => self._RoundIcon, - (self, value) => self._RoundIcon = (string) value - }, { - "SupportsRtl", - "supportsRtl", - self => self._SupportsRtl, - (self, value) => self._SupportsRtl = (bool) value - }, { - "TaskAffinity", - "taskAffinity", - self => self.TaskAffinity, - (self, value) => self.TaskAffinity = (string) value - }, { - "Theme", - "theme", - self => self.Theme, - (self, value) => self.Theme = (string) value - }, { - "UiOptions", - "uiOptions", - self => self._UiOptions, - (self, value) => self._UiOptions = (UiOptions) value - }, { - "UsesCleartextTraffic", - "usesCleartextTraffic", - self => self._UsesCleartextTraffic, - (self, value) => self._UsesCleartextTraffic = (bool) value - }, { - "VMSafeMode", - "vmSafeMode", - self => self._VMSafeMode, - (self, value) => self._VMSafeMode = (bool) value - }, - }; - - ICollection specified; + } + ); + mapping.Add ( + member: "ManageSpaceActivity", + attributeName: "manageSpaceActivity", + getter: self => self.ManageSpaceActivity, + setter: (self, value) => self.ManageSpaceActivity = (Type?) value, + typeof (Type) + ); + mapping.Add ( + member: "Name", + attributeName: "name", + setter: (self, value) => self.Name = (string) value, + attributeValue: ToNameAttribute + ); + } public static ApplicationAttribute FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) { diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/BroadcastReceiverAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/BroadcastReceiverAttribute.Partial.cs index 013b79822da..88bc11a5cf6 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/BroadcastReceiverAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/BroadcastReceiverAttribute.Partial.cs @@ -12,63 +12,6 @@ namespace Android.Content { partial class BroadcastReceiverAttribute { - string _RoundIcon; - - static ManifestDocumentElement mapping = new ManifestDocumentElement ("receiver") { - { - "Description", - "description", - self => self.Description, - (self, value) => self.Description = (string) value - }, { - "DirectBootAware", - "directBootAware", - self => self.DirectBootAware, - (self, value) => self.DirectBootAware = (bool) value - }, { - "Enabled", - "enabled", - self => self.Enabled, - (self, value) => self.Enabled = (bool) value - }, { - "Exported", - "exported", - self => self.Exported, - (self, value) => self.Exported = (bool) value - }, { - "Icon", - "icon", - self => self.Icon, - (self, value) => self.Icon = (string) value - }, { - "Label", - "label", - self => self.Label, - (self, value) => self.Label = (string) value - }, { - "Name", - "name", - self => self.Name, - (self, value) => self.Name = (string) value - }, { - "Permission", - "permission", - self => self.Permission, - (self, value) => self.Permission = (string) value - }, { - "Process", - "process", - self => self.Process, - (self, value) => self.Process = (string) value - }, { - "RoundIcon", - "roundIcon", - self => self._RoundIcon, - (self, value) => self._RoundIcon = (string) value - }, - }; - - ICollection specified; public static BroadcastReceiverAttribute FromTypeDefinition (TypeDefinition type, TypeDefinitionCache cache) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/ContentProviderAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/ContentProviderAttribute.Partial.cs index fcef0600cb7..104072202a4 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/ContentProviderAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/ContentProviderAttribute.Partial.cs @@ -12,91 +12,15 @@ namespace Android.Content { partial class ContentProviderAttribute { - string _RoundIcon; - - static ManifestDocumentElement mapping = new ManifestDocumentElement ("provider") { - { - "Authorities", - "authorities", - (self, value) => self.Authorities = ToStringArray (value), - self => string.Join (";", self.Authorities) - }, { - "DirectBootAware", - "directBootAware", - self => self.DirectBootAware, - (self, value) => self.DirectBootAware = (bool) value - }, { - "Enabled", - "enabled", - self => self.Enabled, - (self, value) => self.Enabled = (bool) value - }, { - "Exported", - "exported", - self => self.Exported, - (self, value) => self.Exported = (bool) value - }, { - "GrantUriPermissions", - "grantUriPermissions", - self => self.GrantUriPermissions, - (self, value) => self.GrantUriPermissions = (bool) value - }, { - "Icon", - "icon", - self => self.Icon, - (self, value) => self.Icon = (string) value - }, { - "InitOrder", - "initOrder", - self => self.InitOrder, - (self, value) => self.InitOrder = (int) value - }, { - "Label", - "label", - self => self.Label, - (self, value) => self.Label = (string) value - }, { - "MultiProcess", - "multiprocess", - self => self.MultiProcess, - (self, value) => self.MultiProcess = (bool) value - }, { - "Name", - "name", - self => self.Name, - (self, value) => self.Name = (string) value - }, { - "Permission", - "permission", - self => self.Permission, - (self, value) => self.Permission = (string) value - }, { - "Process", - "process", - self => self.Process, - (self, value) => self.Process = (string) value - }, { - "ReadPermission", - "readPermission", - self => self.ReadPermission, - (self, value) => self.ReadPermission = (string) value - }, { - "RoundIcon", - "roundIcon", - self => self._RoundIcon, - (self, value) => self._RoundIcon = (string) value - }, { - "Syncable", - "syncable", - self => self.Syncable, - (self, value) => self.Syncable = (bool) value - }, { - "WritePermission", - "writePermission", - self => self.WritePermission, - (self, value) => self.WritePermission = (string) value - }, - }; + static partial void AddManualMapping () + { + mapping.Add ( + member: "Authorities", + attributeName: "authorities", + setter: (self, value) => self.Authorities = ToStringArray (value), + attributeValue: self => string.Join (";", self.Authorities) + ); + } static string[] ToStringArray (object value) { diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/GrantUriPermissionAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/GrantUriPermissionAttribute.Partial.cs index 7fcd62eafef..0526ac2d8ed 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/GrantUriPermissionAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/GrantUriPermissionAttribute.Partial.cs @@ -12,25 +12,6 @@ namespace Android.Content { partial class GrantUriPermissionAttribute { - static ManifestDocumentElement mapping = new ManifestDocumentElement ("grant-uri-permission") { - { - "Path", - "path", - self => self.Path, - (self, value) => self.Path = (string) value - }, { - "PathPattern", - "pathPattern", - self => self.PathPattern, - (self, value) => self.PathPattern = (string) value - }, { - "PathPrefix", - "pathPrefix", - self => self.PathPrefix, - (self, value) => self.PathPrefix = (string) value - }, - }; - ICollection specified; public static IEnumerable FromTypeDefinition (TypeDefinition type, TypeDefinitionCache cache) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs index 41a101a07d6..ae3cc8d31b9 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/InstrumentationAttribute.Partial.cs @@ -12,53 +12,6 @@ namespace Android.App { partial class InstrumentationAttribute { - string _RoundIcon; - string _TargetProcesses; - - static ManifestDocumentElement mapping = new ManifestDocumentElement ("instrumentation") { - { - "FunctionalTest", - "functionalTest", - self => self.FunctionalTest, - (self, value) => self.FunctionalTest = (bool) value - }, { - "HandleProfiling", - "handleProfiling", - self => self.HandleProfiling, - (self, value) => self.HandleProfiling = (bool) value - }, { - "Icon", - "icon", - self => self.Icon, - (self, value) => self.Icon = (string) value - }, { - "Label", - "label", - self => self.Label, - (self, value) => self.Label = (string) value - }, { - "Name", - "name", - self => self.Name, - (self, value) => self.Name = (string) value - }, { - "RoundIcon", - "roundIcon", - self => self._RoundIcon, - (self, value) => self._RoundIcon = (string) value - }, { - "TargetPackage", - "targetPackage", - self => self.TargetPackage, - (self, value) => self.TargetPackage = (string) value - }, { - "TargetProcesses", - "targetProcesses", - self => self._TargetProcesses, - (self, value) => self._TargetProcesses = (string) value - }, - }; - ICollection specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/LayoutAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/LayoutAttribute.Partial.cs index 19afcfea778..076cddcdc62 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/LayoutAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/LayoutAttribute.Partial.cs @@ -17,35 +17,6 @@ namespace Android.App partial class LayoutAttribute { - static ManifestDocumentElement mapping = new ManifestDocumentElement ("layout") { - { - "DefaultWidth", - "defaultWidth", - self => self.DefaultWidth, - (self, value) => self.DefaultWidth = (string) value - }, { - "DefaultHeight", - "defaultHeight", - self => self.DefaultHeight, - (self, value) => self.DefaultHeight = (string) value - }, { - "Gravity", - "gravity", - self => self.Gravity, - (self, value) => self.Gravity = (string) value - }, { - "MinHeight", - "minHeight", - self => self.MinHeight, - (self, value) => self.MinHeight = (string) value - }, { - "MinWidth", - "minWidth", - self => self.MinWidth, - (self, value) => self.MinWidth = (string) value - }, - }; - TypeDefinition type; ICollection specified; diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/MetaDataAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/MetaDataAttribute.Partial.cs index 7e2b5a87d1d..77989ebbf1c 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/MetaDataAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/MetaDataAttribute.Partial.cs @@ -12,25 +12,6 @@ namespace Android.App { partial class MetaDataAttribute { - static ManifestDocumentElement mapping = new ManifestDocumentElement ("meta-data") { - { - "Name", - "name", - self => self.Name, - null - }, { - "Resource", - "resource", - self => self.Resource, - (self, value) => self.Resource = (string) value - }, { - "Value", - "value", - self => self.Value, - (self, value) => self.Value = (string) value - }, - }; - ICollection specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider type, TypeDefinitionCache cache) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs index bbd0b7a8a06..1ca8b28ae39 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionAttribute.Partial.cs @@ -17,47 +17,6 @@ namespace Android.App { partial class PermissionAttribute { - string _RoundIcon; - - static ManifestDocumentElement mapping = new ManifestDocumentElement ("permission") { - { - "Description", - "description", - self => self.Description, - (self, value) => self.Description = (string) value - }, { - "Icon", - "icon", - self => self.Icon, - (self, value) => self.Icon = (string) value - }, { - "Label", - "label", - self => self.Label, - (self, value) => self.Label = (string) value - }, { - "Name", - "name", - self => self.Name, - (self, value) => self.Name = (string) value - }, { - "PermissionGroup", - "permissionGroup", - self => self.PermissionGroup, - (self, value) => self.PermissionGroup = (string) value - }, { - "ProtectionLevel", - "protectionLevel", - self => self.ProtectionLevel, - (self, value) => self.ProtectionLevel = (Protection) value - }, { - "RoundIcon", - "roundIcon", - self => self._RoundIcon, - (self, value) => self._RoundIcon = (string) value - }, - }; - ICollection specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs index 2b71f9e1f64..a1e00e4b68e 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionGroupAttribute.Partial.cs @@ -17,37 +17,6 @@ namespace Android.App { partial class PermissionGroupAttribute { - string _RoundIcon; - - static ManifestDocumentElement mapping = new ManifestDocumentElement ("permission") { - { - "Description", - "description", - self => self.Description, - (self, value) => self.Description = (string) value - }, { - "Icon", - "icon", - self => self.Icon, - (self, value) => self.Icon = (string) value - }, { - "Label", - "label", - self => self.Label, - (self, value) => self.Label = (string) value - }, { - "Name", - "name", - self => self.Name, - (self, value) => self.Name = (string) value - }, { - "RoundIcon", - "roundIcon", - self => self._RoundIcon, - (self, value) => self._RoundIcon = (string) value - }, - }; - ICollection specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs index 17e6d7b3024..0d388e440d3 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/PermissionTreeAttribute.Partial.cs @@ -17,32 +17,6 @@ namespace Android.App { partial class PermissionTreeAttribute { - string _RoundIcon; - - static ManifestDocumentElement mapping = new ManifestDocumentElement ("permission") { - { - "Icon", - "icon", - self => self.Icon, - (self, value) => self.Icon = (string) value - }, { - "Label", - "label", - self => self.Label, - (self, value) => self.Label = (string) value - }, { - "Name", - "name", - self => self.Name, - (self, value) => self.Name = (string) value - }, { - "RoundIcon", - "roundIcon", - self => self._RoundIcon, - (self, value) => self._RoundIcon = (string) value - }, - }; - ICollection specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/ServiceAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/ServiceAttribute.Partial.cs index 9e931e2b3f2..9feed037da4 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/ServiceAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/ServiceAttribute.Partial.cs @@ -14,69 +14,6 @@ namespace Android.App { partial class ServiceAttribute { - bool _IsolatedProcess; - string _RoundIcon; - ForegroundService _ForegroundServiceType; - - static ManifestDocumentElement mapping = new ManifestDocumentElement ("service") { - { - "DirectBootAware", - "directBootAware", - self => self.DirectBootAware, - (self, value) => self.DirectBootAware = (bool) value - }, { - "Enabled", - "enabled", - self => self.Enabled, - (self, value) => self.Enabled = (bool) value - }, { - "Exported", - "exported", - self => self.Exported, - (self, value) => self.Exported = (bool) value - }, { - "ForegroundServiceType", - "foregroundServiceType", - self => self._ForegroundServiceType, - (self, value) => self._ForegroundServiceType = (ForegroundService) value - }, { - "Icon", - "icon", - self => self.Icon, - (self, value) => self.Icon = (string) value - }, { - "IsolatedProcess", - "isolatedProcess", - self => self._IsolatedProcess, - (self, value) => self._IsolatedProcess = (bool) value - }, { - "Label", - "label", - self => self.Label, - (self, value) => self.Label = (string) value - }, { - "Name", - "name", - self => self.Name, - (self, value) => self.Name = (string) value - }, { - "Permission", - "permission", - self => self.Permission, - (self, value) => self.Permission = (string) value - }, { - "Process", - "process", - self => self.Process, - (self, value) => self.Process = (string) value - }, { - "RoundIcon", - "roundIcon", - self => self._RoundIcon, - (self, value) => self._RoundIcon = (string) value - }, - }; - ICollection specified; public static ServiceAttribute FromTypeDefinition (TypeDefinition type, TypeDefinitionCache cache) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesConfigurationAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesConfigurationAttribute.Partial.cs index 8ee69c21d23..5357b555b4b 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesConfigurationAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesConfigurationAttribute.Partial.cs @@ -11,37 +11,6 @@ namespace Android.App { partial class UsesConfigurationAttribute { - bool _Required; - - static ManifestDocumentElement mapping = new ManifestDocumentElement ("uses-configuration") { - { - "ReqFiveWayNav", - "reqFiveWayNav", - self => self.ReqFiveWayNav, - (self, value) => self.ReqFiveWayNav = (bool) value - }, { - "ReqHardKeyboard", - "reqHardKeyboard", - self => self.ReqHardKeyboard, - (self, value) => self.ReqHardKeyboard = (bool) value - }, { - "ReqKeyboardType", - "reqKeyboardType", - self => self.ReqKeyboardType, - (self, value) => self.ReqKeyboardType = (string) value - }, { - "ReqNavigation", - "reqNavigation", - self => self.ReqNavigation, - (self, value) => self.ReqNavigation = (string) value - }, { - "ReqTouchScreen", - "reqTouchScreen", - self => self.ReqTouchScreen, - (self, value) => self.ReqTouchScreen = (string) value - } - }; - internal XElement ToElement (string packageName, TypeDefinitionCache cache) { return mapping.ToElement (this, specified, packageName, cache); diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs index 5b9316bcbdb..58fc679741a 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesFeatureAttribute.Partial.cs @@ -11,32 +11,15 @@ namespace Android.App { partial class UsesFeatureAttribute { - bool _Required; - int _Version; - - static ManifestDocumentElement mapping = new ManifestDocumentElement ("uses-feature") { - { - "Name", - "name", - self => self.Name, - (self, value) => self.Name = (string) value - }, { - "Required", - "required", - self => self._Required, - (self, value) => self._Required = (bool) value - }, { - "GLESVersion", - "glEsVersion", - self => self.GLESVesionAsString(), - (self, value) => self.GLESVersion = (int) value - }, { - "Version", - "version", - self => self._Version, - (self, value) => self._Version = (int) value - } - }; + static partial void AddManualMapping () + { + mapping.Add ( + member: "GLESVersion", + attributeName: "glEsVersion", + getter: self => self.GLESVesionAsString (), + setter: (self, value) => self.GLESVersion = (int) value + ); + } internal string GLESVesionAsString () { diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesLibraryAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesLibraryAttribute.Partial.cs index 0e2c68b9669..10f0aab7e20 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesLibraryAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesLibraryAttribute.Partial.cs @@ -12,20 +12,6 @@ namespace Android.App { partial class UsesLibraryAttribute { - static ManifestDocumentElement mapping = new ManifestDocumentElement ("uses-library") { - { - "Name", - "name", - self => self.Name, - (self, value) => self.Name = (string) value - }, { - "Required", - "required", - self => self.Required, - (self, value) => self.Required = (bool) value - }, - }; - ICollection specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesPermissionAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesPermissionAttribute.Partial.cs index d7d12ce4daf..5ecad9d4fdd 100644 --- a/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesPermissionAttribute.Partial.cs +++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/UsesPermissionAttribute.Partial.cs @@ -12,22 +12,6 @@ namespace Android.App { partial class UsesPermissionAttribute { - int _MaxSdkVersion; - - static ManifestDocumentElement mapping = new ManifestDocumentElement ("uses-permission") { - { - "Name", - "name", - self => self.Name, - (self, value) => self.Name = (string) value - }, { - "MaxSdkVersion", - "maxSdkVersion", - self => self._MaxSdkVersion, - (self, value) => self._MaxSdkVersion = (int) value - }, - }; - ICollection specified; public static IEnumerable FromCustomAttributeProvider (ICustomAttributeProvider provider, TypeDefinitionCache cache) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj index 2f60179a14d..a6cd2267f82 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj @@ -14,7 +14,7 @@ true $(MicrosoftAndroidSdkOutDir) false - $(DefineConstants);TRACE;HAVE_CECIL;MSBUILD;ANDROID_24;ANDROID_26;ANDROID_31;INTERNAL_NULLABLE_ATTRIBUTES + $(DefineConstants);TRACE;HAVE_CECIL;MSBUILD;XABT_MANIFEST_EXTENSIONS ..\..\src\Mono.Android\obj\$(Configuration)\$(DotNetTargetFramework)\android-$(AndroidLatestStablePlatformId)\mcw 8632 false @@ -118,6 +118,9 @@ Mono.Android\UsesPermissionAttribute.cs + + Mono.Android\UsesPermissionAttribute.Partial.cs + Mono.Android\PermissionAttribute.cs diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.cs index fd92917eed1..d818f2b3add 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.cs @@ -125,4 +125,321 @@ public ActivityAttribute () public Android.Views.SoftInput WindowSoftInputMode { get; set; } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("activity"); + + static ActivityAttribute () + { + mapping.Add ( + member: "AllowEmbedded", + attributeName: "allowEmbedded", + getter: self => self.AllowEmbedded, + setter: (self, value) => self.AllowEmbedded = (bool) value + ); + mapping.Add ( + member: "AllowTaskReparenting", + attributeName: "allowTaskReparenting", + getter: self => self.AllowTaskReparenting, + setter: (self, value) => self.AllowTaskReparenting = (bool) value + ); + mapping.Add ( + member: "AlwaysRetainTaskState", + attributeName: "alwaysRetainTaskState", + getter: self => self.AlwaysRetainTaskState, + setter: (self, value) => self.AlwaysRetainTaskState = (bool) value + ); + mapping.Add ( + member: "AutoRemoveFromRecents", + attributeName: "autoRemoveFromRecents", + getter: self => self.AutoRemoveFromRecents, + setter: (self, value) => self.AutoRemoveFromRecents = (bool) value + ); + mapping.Add ( + member: "Banner", + attributeName: "banner", + getter: self => self.Banner, + setter: (self, value) => self.Banner = (string?) value + ); + mapping.Add ( + member: "ClearTaskOnLaunch", + attributeName: "clearTaskOnLaunch", + getter: self => self.ClearTaskOnLaunch, + setter: (self, value) => self.ClearTaskOnLaunch = (bool) value + ); + mapping.Add ( + member: "ColorMode", + attributeName: "colorMode", + getter: self => self.ColorMode, + setter: (self, value) => self.ColorMode = (string?) value + ); + mapping.Add ( + member: "ConfigurationChanges", + attributeName: "configChanges", + getter: self => self.ConfigurationChanges, + setter: (self, value) => self.ConfigurationChanges = (Android.Content.PM.ConfigChanges) value + ); + mapping.Add ( + member: "Description", + attributeName: "description", + getter: self => self.Description, + setter: (self, value) => self.Description = (string?) value + ); + mapping.Add ( + member: "DirectBootAware", + attributeName: "directBootAware", + getter: self => self.DirectBootAware, + setter: (self, value) => self.DirectBootAware = (bool) value + ); + mapping.Add ( + member: "DocumentLaunchMode", + attributeName: "documentLaunchMode", + getter: self => self.DocumentLaunchMode, + setter: (self, value) => self.DocumentLaunchMode = (Android.Content.PM.DocumentLaunchMode) value + ); + mapping.Add ( + member: "Enabled", + attributeName: "enabled", + getter: self => self.Enabled, + setter: (self, value) => self.Enabled = (bool) value + ); + mapping.Add ( + member: "EnableVrMode", + attributeName: "enableVrMode", + getter: self => self.EnableVrMode, + setter: (self, value) => self.EnableVrMode = (string?) value + ); + mapping.Add ( + member: "ExcludeFromRecents", + attributeName: "excludeFromRecents", + getter: self => self.ExcludeFromRecents, + setter: (self, value) => self.ExcludeFromRecents = (bool) value + ); + mapping.Add ( + member: "Exported", + attributeName: "exported", + getter: self => self.Exported, + setter: (self, value) => self.Exported = (bool) value + ); + mapping.Add ( + member: "FinishOnCloseSystemDialogs", + attributeName: "finishOnCloseSystemDialogs", + getter: self => self.FinishOnCloseSystemDialogs, + setter: (self, value) => self.FinishOnCloseSystemDialogs = (bool) value + ); + mapping.Add ( + member: "FinishOnTaskLaunch", + attributeName: "finishOnTaskLaunch", + getter: self => self.FinishOnTaskLaunch, + setter: (self, value) => self.FinishOnTaskLaunch = (bool) value + ); + mapping.Add ( + member: "HardwareAccelerated", + attributeName: "hardwareAccelerated", + getter: self => self.HardwareAccelerated, + setter: (self, value) => self.HardwareAccelerated = (bool) value + ); + mapping.Add ( + member: "Icon", + attributeName: "icon", + getter: self => self.Icon, + setter: (self, value) => self.Icon = (string?) value + ); + mapping.Add ( + member: "Immersive", + attributeName: "immersive", + getter: self => self.Immersive, + setter: (self, value) => self.Immersive = (bool) value + ); + mapping.Add ( + member: "Label", + attributeName: "label", + getter: self => self.Label, + setter: (self, value) => self.Label = (string?) value + ); + mapping.Add ( + member: "LaunchMode", + attributeName: "launchMode", + getter: self => self.LaunchMode, + setter: (self, value) => self.LaunchMode = (Android.Content.PM.LaunchMode) value + ); + mapping.Add ( + member: "LockTaskMode", + attributeName: "lockTaskMode", + getter: self => self.LockTaskMode, + setter: (self, value) => self.LockTaskMode = (string?) value + ); + mapping.Add ( + member: "Logo", + attributeName: "logo", + getter: self => self.Logo, + setter: (self, value) => self.Logo = (string?) value + ); + mapping.Add ( + member: "MaxAspectRatio", + attributeName: "maxAspectRatio", + getter: self => self.MaxAspectRatio, + setter: (self, value) => self.MaxAspectRatio = (float) value + ); + mapping.Add ( + member: "MaxRecents", + attributeName: "maxRecents", + getter: self => self.MaxRecents, + setter: (self, value) => self.MaxRecents = (int) value + ); + mapping.Add ( + member: "MultiProcess", + attributeName: "multiprocess", + getter: self => self.MultiProcess, + setter: (self, value) => self.MultiProcess = (bool) value + ); + mapping.Add ( + member: "Name", + attributeName: "name", + getter: self => self.Name, + setter: (self, value) => self.Name = (string?) value + ); + mapping.Add ( + member: "NoHistory", + attributeName: "noHistory", + getter: self => self.NoHistory, + setter: (self, value) => self.NoHistory = (bool) value + ); + mapping.Add ( + member: "Permission", + attributeName: "permission", + getter: self => self.Permission, + setter: (self, value) => self.Permission = (string?) value + ); + mapping.Add ( + member: "PersistableMode", + attributeName: "persistableMode", + getter: self => self.PersistableMode, + setter: (self, value) => self.PersistableMode = (Android.Content.PM.ActivityPersistableMode) value + ); + mapping.Add ( + member: "Process", + attributeName: "process", + getter: self => self.Process, + setter: (self, value) => self.Process = (string?) value + ); + mapping.Add ( + member: "RecreateOnConfigChanges", + attributeName: "recreateOnConfigChanges", + getter: self => self.RecreateOnConfigChanges, + setter: (self, value) => self.RecreateOnConfigChanges = (Android.Content.PM.ConfigChanges) value + ); + mapping.Add ( + member: "RelinquishTaskIdentity", + attributeName: "relinquishTaskIdentity", + getter: self => self.RelinquishTaskIdentity, + setter: (self, value) => self.RelinquishTaskIdentity = (bool) value + ); + mapping.Add ( + member: "ResizeableActivity", + attributeName: "resizeableActivity", + getter: self => self.ResizeableActivity, + setter: (self, value) => self.ResizeableActivity = (bool) value + ); + mapping.Add ( + member: "ResumeWhilePausing", + attributeName: "resumeWhilePausing", + getter: self => self.ResumeWhilePausing, + setter: (self, value) => self.ResumeWhilePausing = (bool) value + ); + mapping.Add ( + member: "RotationAnimation", + attributeName: "rotationAnimation", + getter: self => self.RotationAnimation, + setter: (self, value) => self.RotationAnimation = (Android.Views.WindowRotationAnimation) value + ); + mapping.Add ( + member: "RoundIcon", + attributeName: "roundIcon", + getter: self => self.RoundIcon, + setter: (self, value) => self.RoundIcon = (string?) value + ); + mapping.Add ( + member: "ScreenOrientation", + attributeName: "screenOrientation", + getter: self => self.ScreenOrientation, + setter: (self, value) => self.ScreenOrientation = (Android.Content.PM.ScreenOrientation) value + ); + mapping.Add ( + member: "ShowForAllUsers", + attributeName: "showForAllUsers", + getter: self => self.ShowForAllUsers, + setter: (self, value) => self.ShowForAllUsers = (bool) value + ); + mapping.Add ( + member: "ShowOnLockScreen", + attributeName: "showOnLockScreen", + getter: self => self.ShowOnLockScreen, + setter: (self, value) => self.ShowOnLockScreen = (bool) value + ); + mapping.Add ( + member: "ShowWhenLocked", + attributeName: "showWhenLocked", + getter: self => self.ShowWhenLocked, + setter: (self, value) => self.ShowWhenLocked = (bool) value + ); + mapping.Add ( + member: "SingleUser", + attributeName: "singleUser", + getter: self => self.SingleUser, + setter: (self, value) => self.SingleUser = (bool) value + ); + mapping.Add ( + member: "StateNotNeeded", + attributeName: "stateNotNeeded", + getter: self => self.StateNotNeeded, + setter: (self, value) => self.StateNotNeeded = (bool) value + ); + mapping.Add ( + member: "SupportsPictureInPicture", + attributeName: "supportsPictureInPicture", + getter: self => self.SupportsPictureInPicture, + setter: (self, value) => self.SupportsPictureInPicture = (bool) value + ); + mapping.Add ( + member: "TaskAffinity", + attributeName: "taskAffinity", + getter: self => self.TaskAffinity, + setter: (self, value) => self.TaskAffinity = (string?) value + ); + mapping.Add ( + member: "Theme", + attributeName: "theme", + getter: self => self.Theme, + setter: (self, value) => self.Theme = (string?) value + ); + mapping.Add ( + member: "TurnScreenOn", + attributeName: "turnScreenOn", + getter: self => self.TurnScreenOn, + setter: (self, value) => self.TurnScreenOn = (bool) value + ); + mapping.Add ( + member: "UiOptions", + attributeName: "uiOptions", + getter: self => self.UiOptions, + setter: (self, value) => self.UiOptions = (Android.Content.PM.UiOptions) value + ); + mapping.Add ( + member: "VisibleToInstantApps", + attributeName: "visibleToInstantApps", + getter: self => self.VisibleToInstantApps, + setter: (self, value) => self.VisibleToInstantApps = (bool) value + ); + mapping.Add ( + member: "WindowSoftInputMode", + attributeName: "windowSoftInputMode", + getter: self => self.WindowSoftInputMode, + setter: (self, value) => self.WindowSoftInputMode = (Android.Views.SoftInput) value + ); + + AddManualMapping (); + } + + static partial void AddManualMapping (); +#endif } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ApplicationAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ApplicationAttribute.cs index f594a51cbed..38c9aeaf5a4 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ApplicationAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ApplicationAttribute.cs @@ -94,4 +94,219 @@ public ApplicationAttribute () public bool VMSafeMode { get; set; } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("application"); + + static ApplicationAttribute () + { + mapping.Add ( + member: "AllowBackup", + attributeName: "allowBackup", + getter: self => self.AllowBackup, + setter: (self, value) => self.AllowBackup = (bool) value + ); + mapping.Add ( + member: "AllowClearUserData", + attributeName: "allowClearUserData", + getter: self => self.AllowClearUserData, + setter: (self, value) => self.AllowClearUserData = (bool) value + ); + mapping.Add ( + member: "AllowTaskReparenting", + attributeName: "allowTaskReparenting", + getter: self => self.AllowTaskReparenting, + setter: (self, value) => self.AllowTaskReparenting = (bool) value + ); + mapping.Add ( + member: "BackupInForeground", + attributeName: "backupInForeground", + getter: self => self.BackupInForeground, + setter: (self, value) => self.BackupInForeground = (bool) value + ); + mapping.Add ( + member: "Banner", + attributeName: "banner", + getter: self => self.Banner, + setter: (self, value) => self.Banner = (string?) value + ); + mapping.Add ( + member: "Debuggable", + attributeName: "debuggable", + getter: self => self.Debuggable, + setter: (self, value) => self.Debuggable = (bool) value + ); + mapping.Add ( + member: "Description", + attributeName: "description", + getter: self => self.Description, + setter: (self, value) => self.Description = (string?) value + ); + mapping.Add ( + member: "DirectBootAware", + attributeName: "directBootAware", + getter: self => self.DirectBootAware, + setter: (self, value) => self.DirectBootAware = (bool) value + ); + mapping.Add ( + member: "Enabled", + attributeName: "enabled", + getter: self => self.Enabled, + setter: (self, value) => self.Enabled = (bool) value + ); + mapping.Add ( + member: "ExtractNativeLibs", + attributeName: "extractNativeLibs", + getter: self => self.ExtractNativeLibs, + setter: (self, value) => self.ExtractNativeLibs = (bool) value + ); + mapping.Add ( + member: "FullBackupContent", + attributeName: "fullBackupContent", + getter: self => self.FullBackupContent, + setter: (self, value) => self.FullBackupContent = (bool) value + ); + mapping.Add ( + member: "FullBackupOnly", + attributeName: "fullBackupOnly", + getter: self => self.FullBackupOnly, + setter: (self, value) => self.FullBackupOnly = (bool) value + ); + mapping.Add ( + member: "HardwareAccelerated", + attributeName: "hardwareAccelerated", + getter: self => self.HardwareAccelerated, + setter: (self, value) => self.HardwareAccelerated = (bool) value + ); + mapping.Add ( + member: "HasCode", + attributeName: "hasCode", + getter: self => self.HasCode, + setter: (self, value) => self.HasCode = (bool) value + ); + mapping.Add ( + member: "Icon", + attributeName: "icon", + getter: self => self.Icon, + setter: (self, value) => self.Icon = (string?) value + ); + mapping.Add ( + member: "KillAfterRestore", + attributeName: "killAfterRestore", + getter: self => self.KillAfterRestore, + setter: (self, value) => self.KillAfterRestore = (bool) value + ); + mapping.Add ( + member: "Label", + attributeName: "label", + getter: self => self.Label, + setter: (self, value) => self.Label = (string?) value + ); + mapping.Add ( + member: "LargeHeap", + attributeName: "largeHeap", + getter: self => self.LargeHeap, + setter: (self, value) => self.LargeHeap = (bool) value + ); + mapping.Add ( + member: "Logo", + attributeName: "logo", + getter: self => self.Logo, + setter: (self, value) => self.Logo = (string?) value + ); + mapping.Add ( + member: "NetworkSecurityConfig", + attributeName: "networkSecurityConfig", + getter: self => self.NetworkSecurityConfig, + setter: (self, value) => self.NetworkSecurityConfig = (string?) value + ); + mapping.Add ( + member: "Permission", + attributeName: "permission", + getter: self => self.Permission, + setter: (self, value) => self.Permission = (string?) value + ); + mapping.Add ( + member: "Persistent", + attributeName: "persistent", + getter: self => self.Persistent, + setter: (self, value) => self.Persistent = (bool) value + ); + mapping.Add ( + member: "Process", + attributeName: "process", + getter: self => self.Process, + setter: (self, value) => self.Process = (string?) value + ); + mapping.Add ( + member: "RequiredAccountType", + attributeName: "requiredAccountType", + getter: self => self.RequiredAccountType, + setter: (self, value) => self.RequiredAccountType = (string?) value + ); + mapping.Add ( + member: "ResizeableActivity", + attributeName: "resizeableActivity", + getter: self => self.ResizeableActivity, + setter: (self, value) => self.ResizeableActivity = (bool) value + ); + mapping.Add ( + member: "RestoreAnyVersion", + attributeName: "restoreAnyVersion", + getter: self => self.RestoreAnyVersion, + setter: (self, value) => self.RestoreAnyVersion = (bool) value + ); + mapping.Add ( + member: "RestrictedAccountType", + attributeName: "restrictedAccountType", + getter: self => self.RestrictedAccountType, + setter: (self, value) => self.RestrictedAccountType = (string?) value + ); + mapping.Add ( + member: "RoundIcon", + attributeName: "roundIcon", + getter: self => self.RoundIcon, + setter: (self, value) => self.RoundIcon = (string?) value + ); + mapping.Add ( + member: "SupportsRtl", + attributeName: "supportsRtl", + getter: self => self.SupportsRtl, + setter: (self, value) => self.SupportsRtl = (bool) value + ); + mapping.Add ( + member: "TaskAffinity", + attributeName: "taskAffinity", + getter: self => self.TaskAffinity, + setter: (self, value) => self.TaskAffinity = (string?) value + ); + mapping.Add ( + member: "Theme", + attributeName: "theme", + getter: self => self.Theme, + setter: (self, value) => self.Theme = (string?) value + ); + mapping.Add ( + member: "UiOptions", + attributeName: "uiOptions", + getter: self => self.UiOptions, + setter: (self, value) => self.UiOptions = (Android.Content.PM.UiOptions) value + ); + mapping.Add ( + member: "UsesCleartextTraffic", + attributeName: "usesCleartextTraffic", + getter: self => self.UsesCleartextTraffic, + setter: (self, value) => self.UsesCleartextTraffic = (bool) value + ); + mapping.Add ( + member: "VMSafeMode", + attributeName: "vmSafeMode", + getter: self => self.VMSafeMode, + setter: (self, value) => self.VMSafeMode = (bool) value + ); + + AddManualMapping (); + } + + static partial void AddManualMapping (); +#endif } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/InstrumentationAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/InstrumentationAttribute.cs index 6edc553b90c..a80caf7893d 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.App/InstrumentationAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/InstrumentationAttribute.cs @@ -36,4 +36,63 @@ public InstrumentationAttribute () public string? TargetProcesses { get; set; } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("instrumentation"); + + static InstrumentationAttribute () + { + mapping.Add ( + member: "FunctionalTest", + attributeName: "functionalTest", + getter: self => self.FunctionalTest, + setter: (self, value) => self.FunctionalTest = (bool) value + ); + mapping.Add ( + member: "HandleProfiling", + attributeName: "handleProfiling", + getter: self => self.HandleProfiling, + setter: (self, value) => self.HandleProfiling = (bool) value + ); + mapping.Add ( + member: "Icon", + attributeName: "icon", + getter: self => self.Icon, + setter: (self, value) => self.Icon = (string?) value + ); + mapping.Add ( + member: "Label", + attributeName: "label", + getter: self => self.Label, + setter: (self, value) => self.Label = (string?) value + ); + mapping.Add ( + member: "Name", + attributeName: "name", + getter: self => self.Name, + setter: (self, value) => self.Name = (string?) value + ); + mapping.Add ( + member: "RoundIcon", + attributeName: "roundIcon", + getter: self => self.RoundIcon, + setter: (self, value) => self.RoundIcon = (string?) value + ); + mapping.Add ( + member: "TargetPackage", + attributeName: "targetPackage", + getter: self => self.TargetPackage, + setter: (self, value) => self.TargetPackage = (string?) value + ); + mapping.Add ( + member: "TargetProcesses", + attributeName: "targetProcesses", + getter: self => self.TargetProcesses, + setter: (self, value) => self.TargetProcesses = (string?) value + ); + + AddManualMapping (); + } + + static partial void AddManualMapping (); +#endif } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/LayoutAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/LayoutAttribute.cs index 15d52290f66..fd41ef39b8d 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.App/LayoutAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/LayoutAttribute.cs @@ -30,4 +30,45 @@ public LayoutAttribute () public string? MinWidth { get; set; } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("layout"); + + static LayoutAttribute () + { + mapping.Add ( + member: "DefaultHeight", + attributeName: "defaultHeight", + getter: self => self.DefaultHeight, + setter: (self, value) => self.DefaultHeight = (string?) value + ); + mapping.Add ( + member: "DefaultWidth", + attributeName: "defaultWidth", + getter: self => self.DefaultWidth, + setter: (self, value) => self.DefaultWidth = (string?) value + ); + mapping.Add ( + member: "Gravity", + attributeName: "gravity", + getter: self => self.Gravity, + setter: (self, value) => self.Gravity = (string?) value + ); + mapping.Add ( + member: "MinHeight", + attributeName: "minHeight", + getter: self => self.MinHeight, + setter: (self, value) => self.MinHeight = (string?) value + ); + mapping.Add ( + member: "MinWidth", + attributeName: "minWidth", + getter: self => self.MinWidth, + setter: (self, value) => self.MinWidth = (string?) value + ); + + AddManualMapping (); + } + + static partial void AddManualMapping (); +#endif } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ServiceAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ServiceAttribute.cs index 2eaf442b666..1871978de39 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ServiceAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ServiceAttribute.cs @@ -42,4 +42,81 @@ public ServiceAttribute () public string? RoundIcon { get; set; } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("service"); + + static ServiceAttribute () + { + mapping.Add ( + member: "DirectBootAware", + attributeName: "directBootAware", + getter: self => self.DirectBootAware, + setter: (self, value) => self.DirectBootAware = (bool) value + ); + mapping.Add ( + member: "Enabled", + attributeName: "enabled", + getter: self => self.Enabled, + setter: (self, value) => self.Enabled = (bool) value + ); + mapping.Add ( + member: "Exported", + attributeName: "exported", + getter: self => self.Exported, + setter: (self, value) => self.Exported = (bool) value + ); + mapping.Add ( + member: "ForegroundServiceType", + attributeName: "foregroundServiceType", + getter: self => self.ForegroundServiceType, + setter: (self, value) => self.ForegroundServiceType = (Android.Content.PM.ForegroundService) value + ); + mapping.Add ( + member: "Icon", + attributeName: "icon", + getter: self => self.Icon, + setter: (self, value) => self.Icon = (string?) value + ); + mapping.Add ( + member: "IsolatedProcess", + attributeName: "isolatedProcess", + getter: self => self.IsolatedProcess, + setter: (self, value) => self.IsolatedProcess = (bool) value + ); + mapping.Add ( + member: "Label", + attributeName: "label", + getter: self => self.Label, + setter: (self, value) => self.Label = (string?) value + ); + mapping.Add ( + member: "Name", + attributeName: "name", + getter: self => self.Name, + setter: (self, value) => self.Name = (string?) value + ); + mapping.Add ( + member: "Permission", + attributeName: "permission", + getter: self => self.Permission, + setter: (self, value) => self.Permission = (string?) value + ); + mapping.Add ( + member: "Process", + attributeName: "process", + getter: self => self.Process, + setter: (self, value) => self.Process = (string?) value + ); + mapping.Add ( + member: "RoundIcon", + attributeName: "roundIcon", + getter: self => self.RoundIcon, + setter: (self, value) => self.RoundIcon = (string?) value + ); + + AddManualMapping (); + } + + static partial void AddManualMapping (); +#endif } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.Content/BroadcastReceiverAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.Content/BroadcastReceiverAttribute.cs index e2b7fedaa40..fcdf109d6b8 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.Content/BroadcastReceiverAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.Content/BroadcastReceiverAttribute.cs @@ -40,4 +40,75 @@ public BroadcastReceiverAttribute () public string? RoundIcon { get; set; } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("receiver"); + + static BroadcastReceiverAttribute () + { + mapping.Add ( + member: "Description", + attributeName: "description", + getter: self => self.Description, + setter: (self, value) => self.Description = (string?) value + ); + mapping.Add ( + member: "DirectBootAware", + attributeName: "directBootAware", + getter: self => self.DirectBootAware, + setter: (self, value) => self.DirectBootAware = (bool) value + ); + mapping.Add ( + member: "Enabled", + attributeName: "enabled", + getter: self => self.Enabled, + setter: (self, value) => self.Enabled = (bool) value + ); + mapping.Add ( + member: "Exported", + attributeName: "exported", + getter: self => self.Exported, + setter: (self, value) => self.Exported = (bool) value + ); + mapping.Add ( + member: "Icon", + attributeName: "icon", + getter: self => self.Icon, + setter: (self, value) => self.Icon = (string?) value + ); + mapping.Add ( + member: "Label", + attributeName: "label", + getter: self => self.Label, + setter: (self, value) => self.Label = (string?) value + ); + mapping.Add ( + member: "Name", + attributeName: "name", + getter: self => self.Name, + setter: (self, value) => self.Name = (string?) value + ); + mapping.Add ( + member: "Permission", + attributeName: "permission", + getter: self => self.Permission, + setter: (self, value) => self.Permission = (string?) value + ); + mapping.Add ( + member: "Process", + attributeName: "process", + getter: self => self.Process, + setter: (self, value) => self.Process = (string?) value + ); + mapping.Add ( + member: "RoundIcon", + attributeName: "roundIcon", + getter: self => self.RoundIcon, + setter: (self, value) => self.RoundIcon = (string?) value + ); + + AddManualMapping (); + } + + static partial void AddManualMapping (); +#endif } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.cs index 41976ef02cb..ccd6f220801 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.cs @@ -48,4 +48,105 @@ public partial class ContentProviderAttribute : Attribute, Java.Interop.IJniName public string? WritePermission { get; set; } +#if XABT_MANIFEST_EXTENSIONS + static Xamarin.Android.Manifest.ManifestDocumentElement mapping = new ("provider"); + + static ContentProviderAttribute () + { + mapping.Add ( + member: "DirectBootAware", + attributeName: "directBootAware", + getter: self => self.DirectBootAware, + setter: (self, value) => self.DirectBootAware = (bool) value + ); + mapping.Add ( + member: "Enabled", + attributeName: "enabled", + getter: self => self.Enabled, + setter: (self, value) => self.Enabled = (bool) value + ); + mapping.Add ( + member: "Exported", + attributeName: "exported", + getter: self => self.Exported, + setter: (self, value) => self.Exported = (bool) value + ); + mapping.Add ( + member: "GrantUriPermissions", + attributeName: "grantUriPermissions", + getter: self => self.GrantUriPermissions, + setter: (self, value) => self.GrantUriPermissions = (bool) value + ); + mapping.Add ( + member: "Icon", + attributeName: "icon", + getter: self => self.Icon, + setter: (self, value) => self.Icon = (string?) value + ); + mapping.Add ( + member: "InitOrder", + attributeName: "initOrder", + getter: self => self.InitOrder, + setter: (self, value) => self.InitOrder = (int) value + ); + mapping.Add ( + member: "Label", + attributeName: "label", + getter: self => self.Label, + setter: (self, value) => self.Label = (string?) value + ); + mapping.Add ( + member: "MultiProcess", + attributeName: "multiprocess", + getter: self => self.MultiProcess, + setter: (self, value) => self.MultiProcess = (bool) value + ); + mapping.Add ( + member: "Name", + attributeName: "name", + getter: self => self.Name, + setter: (self, value) => self.Name = (string?) value + ); + mapping.Add ( + member: "Permission", + attributeName: "permission", + getter: self => self.Permission, + setter: (self, value) => self.Permission = (string?) value + ); + mapping.Add ( + member: "Process", + attributeName: "process", + getter: self => self.Process, + setter: (self, value) => self.Process = (string?) value + ); + mapping.Add ( + member: "ReadPermission", + attributeName: "readPermission", + getter: self => self.ReadPermission, + setter: (self, value) => self.ReadPermission = (string?) value + ); + mapping.Add ( + member: "RoundIcon", + attributeName: "roundIcon", + getter: self => self.RoundIcon, + setter: (self, value) => self.RoundIcon = (string?) value + ); + mapping.Add ( + member: "Syncable", + attributeName: "syncable", + getter: self => self.Syncable, + setter: (self, value) => self.Syncable = (bool) value + ); + mapping.Add ( + member: "WritePermission", + attributeName: "writePermission", + getter: self => self.WritePermission, + setter: (self, value) => self.WritePermission = (string?) value + ); + + AddManualMapping (); + } + + static partial void AddManualMapping (); +#endif } From 56122eb20b1b88bad62dcf58bef6ff2840eb1d9d Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Fri, 17 May 2024 13:47:20 -1000 Subject: [PATCH 3/4] Additional documentation. --- .../manifest-attribute-codegen/README.md | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/build-tools/manifest-attribute-codegen/README.md b/build-tools/manifest-attribute-codegen/README.md index e0122729ff0..207cb8c0a11 100644 --- a/build-tools/manifest-attribute-codegen/README.md +++ b/build-tools/manifest-attribute-codegen/README.md @@ -1,8 +1,8 @@ # What is this? -`manifest-attribute-codegen` a tool that collects Android SDK -resource information about what XML elements can be placed in an AndroidManifest.xml, then generate a unified -element/attribute definition with "which API introduced this" information. +`manifest-attribute-codegen` a tool that collects Android SDK resource information about what +XML elements can be placed in an AndroidManifest.xml (from Android SDK `attrs_manifest.xml` files), +then generate a unified element/attribute definition with "which API introduced this" information. Using this information, we can generate `[(Application|Activity|etc)Attribute]` classes that can be used by both `Mono.Android` and `Xamarin.Android.Build.Tasks`. @@ -26,7 +26,29 @@ dotnet build -t:GenerateManifestAttributes If all found elements/attributes are accounted for in `metadata.xml`, new `*Attribute.cs` files will be generated. -If everything isn't accounted for, you will be required to specify how to handle the new pieces. +If everything isn't accounted for, a list of unaccounted elements/attributes will be specified +in the error output, and you will be required to specify how to handle the new pieces. + +# Metadata file structure + +There are two instances of entries in the `metadata.xml` file: `type` and `element`. These represent +valid instances of entries and attributes respectively that can be placed in an `AndroidManifest.xml` file +as specified in the Android SDK `attrs_manifest.xml` files. + +For example, the following valid `AndroidManifestxml` entry: + +```xml + +``` + +would be represented with the following `metadata.xml` entries: + +```xml + + +``` + +The required/optional attributes for `` and `` are described below. # Handling new types (elements) @@ -93,6 +115,10 @@ To surface the attribute: ``` +Required metadata + +- **path** - A specifier for this attribute, of the form `{element_name}.{attribute_name}` + Optional metadata (note that if any metadata is set, `visible` is assumed to be `true` unless specified otherwise): - **type** - C# type to override missing type information from the manifest definition @@ -100,6 +126,3 @@ Optional metadata (note that if any metadata is set, `visible` is assumed to be - **obsolete** - A string describing the reason for this member being `[Obsolete ("foo")]` - **readonly** - Whether to generate the property with a `private set`, defaults to `false` - **manualMap** - Whether to exclude the property from the `mapping` field used by `Xamarin.Android.Build.Tasks, defaults to `false` - - - From a88f5836b7794eaca5d0dce5b7d86f587f2535e2 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Thu, 6 Jun 2024 20:16:48 -0400 Subject: [PATCH 4/4] Various review bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review and update `README.md` so that @jonpryor understands it. In particular, `xaprepare android-sdk-platforms=all` Is Not A Thing™ and needed to be replaced with a command that actually worked. Update `manifest-attribute-codegen` to: * Normalize the output path so that it works properly on macOS/Linux * Has a comment after `#endif // XABT_MANIFEST_EXTENSIONS`, because @jonpryor thinks code is clearer that way. (This is also how I found out that paths needed to be normalized!) * Remove extraneous whitespace from ``. * Update the `GenerateManifestAttributes` target so that `-output-manifest` is used to update `manifest-definition.xml`. The change of the `#endif` required updating lots of source code. --- .../manifest-attribute-codegen/Program.cs | 4 +- .../manifest-attribute-codegen/README.md | 91 +++--- .../SourceWriters/AttributeDataClass.cs | 2 +- .../manifest-attribute-codegen.csproj | 5 +- .../manifest-definition.xml | 260 +++++++++++++++--- .../Android.App/MetaDataAttribute.cs | 2 +- .../Android.App/PermissionAttribute.cs | 2 +- .../Android.App/PermissionGroupAttribute.cs | 2 +- .../Android.App/PermissionTreeAttribute.cs | 2 +- .../Android.App/UsesConfigurationAttribute.cs | 2 +- .../Android.App/UsesFeatureAttribute.cs | 2 +- .../Android.App/UsesLibraryAttribute.cs | 2 +- .../Android.App/UsesPermissionAttribute.cs | 2 +- .../GrantUriPermissionAttribute.cs | 2 +- .../Android.App/ActivityAttribute.cs | 2 +- .../Android.App/ApplicationAttribute.cs | 2 +- .../Android.App/InstrumentationAttribute.cs | 2 +- .../Android.App/LayoutAttribute.cs | 2 +- .../Android.App/ServiceAttribute.cs | 2 +- .../BroadcastReceiverAttribute.cs | 2 +- .../ContentProviderAttribute.cs | 2 +- 21 files changed, 296 insertions(+), 98 deletions(-) diff --git a/build-tools/manifest-attribute-codegen/Program.cs b/build-tools/manifest-attribute-codegen/Program.cs index 17f28e4aa6a..87261f4ba1d 100644 --- a/build-tools/manifest-attribute-codegen/Program.cs +++ b/build-tools/manifest-attribute-codegen/Program.cs @@ -1,3 +1,4 @@ +using System.IO; using Mono.Options; using Xamarin.SourceWriter; @@ -83,7 +84,8 @@ public static int Main (string [] args) // Generate manifest attributes C# code foreach (var type in metadata.Types.Values.Where (t => !t.Ignore)) { - using var w = new StreamWriter (Path.Combine (base_dir, type.OutputFile)); + var path = Path.Combine (base_dir, type.OutputFile.Replace ('\\', Path.DirectorySeparatorChar)); + using var w = new StreamWriter (path); using var cw = new CodeWriter (w); var element = merged.Elements.First (_ => _.ActualElementName == type.Name); var writer = AttributeDataClass.Create (element, metadata, type); diff --git a/build-tools/manifest-attribute-codegen/README.md b/build-tools/manifest-attribute-codegen/README.md index 207cb8c0a11..26f0794e030 100644 --- a/build-tools/manifest-attribute-codegen/README.md +++ b/build-tools/manifest-attribute-codegen/README.md @@ -1,54 +1,73 @@ # What is this? -`manifest-attribute-codegen` a tool that collects Android SDK resource information about what -XML elements can be placed in an AndroidManifest.xml (from Android SDK `attrs_manifest.xml` files), -then generate a unified element/attribute definition with "which API introduced this" information. +`manifest-attribute-codegen` a tool that: -Using this information, we can generate `[(Application|Activity|etc)Attribute]` classes that can be used + 1. Collects Android SDK resource information about what XML elements can be placed in an + `AndroidManifest.xml` by reading Android SDK `attrs_manifest.xml` files, and + 2. Verifies that `metadata.xml` (within this directory) appropriately mirrors (1), and + 3. (Optionally) emits `manifest-definition.xml` (within this directory), based on (1), + which specifies in which API level a given element or attribute was added. + +Using `metadata.xml`, we can generate `[(Application|Activity|etc)Attribute]` classes that can be used by both `Mono.Android` and `Xamarin.Android.Build.Tasks`. This generally only needs to be done each time we bind a new Android API level. # How to use -Ensure all Android platform SDK levels are installed. This can be done with `xaprepare`: +Ensure all Android platform SDK levels are installed. This can be done with `xaprepare`; +run the following command from the checkout toplevel: -``` -xaprepare android-sdk-platforms=all +```dotnetcli +dotnet run --project "build-tools/xaprepare/xaprepare/xaprepare.csproj" -- -s AndroidTestDependencies --android-sdk-platforms=all ``` -From this directory, run: +Next, from this directory, run: -``` +```sh dotnet build -t:GenerateManifestAttributes + +# alternatively, from toplevel +(cd build-tools/manifest-attribute-codegen && dotnet build -t:GenerateManifestAttributes) ``` -If all found elements/attributes are accounted for in `metadata.xml`, new `*Attribute.cs` files -will be generated. +If (1) and (2) are consistent with each other, new `*Attribute.cs` files will be generated. -If everything isn't accounted for, a list of unaccounted elements/attributes will be specified +If (1) and (2) are *inconsistent* -- typically because a new element or attribute was added to +`AndroidManifest.xml` -- then a list of unaccounted elements and/or attributes will be specified in the error output, and you will be required to specify how to handle the new pieces. -# Metadata file structure +# `metadata.xml` file structure -There are two instances of entries in the `metadata.xml` file: `type` and `element`. These represent -valid instances of entries and attributes respectively that can be placed in an `AndroidManifest.xml` file -as specified in the Android SDK `attrs_manifest.xml` files. +There are two types of elements in `metadata.xml` file: `` and ``. +These represent valid instances of entries and attributes respectively that can be placed in an +`AndroidManifest.xml` file as specified in the Android SDK `attrs_manifest.xml` files. -For example, the following valid `AndroidManifestxml` entry: +For example, consider the following valid `AndroidManifest.xml` entry: ```xml ``` -would be represented with the following `metadata.xml` entries: +This is partially declared within the Android SDK `attrs_manifest.xml` as: + +```xml + + + +``` + +(Note: a degree of "squinting" must be done to map `AndroidManifestActivity` to `activity`.) + +The `` element is represented in `metadata.xml` via both a `` +and an `` entry: ```xml ``` -The required/optional attributes for `` and `` are described below. +The required/optional attributes for `` and `` are described further below. # Handling new types (elements) @@ -60,7 +79,7 @@ ignore it or bind it. The majority of the found types are not bound so the most likely scenario may be to ignore the new type: ```xml - + ``` ## Bind the type @@ -71,23 +90,23 @@ Alternatively, the type can be bound: ``` -Required metadata: +Required attributes: -- **name** - The name of the new element in AndroidManifest.xml, like `activity` or `application` +- **name** - The name of the new element in `AndroidManifest.xml`, like `activity` or `application` - **namespace** - The C# namespace the element will be placed in -- **outputFile** - The path to write the generated .cs +- **outputFile** - The path to write the generated `.cs` - **usage** - The `validOn` attribute usage information passed to `[AttributeUsage]` -Optional metadata: +Optional attributes: -- **allowMultiple** - The `allowMultiple` attribute usage information passed to `[AttributeUsage]`, defaults to `false` -- **jniNameProvider** - Whether the attribute should implement `Java.Interop.IJniNameProviderAttribute`, defaults to `false` -- **defaultConstructor** - Whether a parameterless constructor should be generated, defaults to `true` -- **sealed** - Whether the attribute type should be `sealed`, defaults to `true` +- **allowMultiple** - The `allowMultiple` attribute usage information passed to `[AttributeUsage]`; defaults to `false` +- **jniNameProvider** - Whether the attribute should implement `Java.Interop.IJniNameProviderAttribute`; defaults to `false` +- **defaultConstructor** - Whether a parameterless constructor should be generated; defaults to `true` +- **sealed** - Whether the attribute type should be `sealed`; defaults to `true` - **managedName** - The name of the managed attribute class if the default isn't correct -- **generateMapping** - Whether to generate the `mapping` field used by `Xamarin.Android.Build.Tasks, defaults to `true` +- **generateMapping** - Whether to generate the `mapping` field used by `Xamarin.Android.Build.Tasks`; defaults to `true` -Note that if a new type is created, there will be additional manual code that needs to written to configure +Note that if a new type is created, there will be additional manual code that needs to be written to configure `Xamarin.Android.Build.Tasks` to translate the attribute to AndroidManifest xml. Example: @@ -97,14 +116,14 @@ Example: # Handling new attributes -When a new attribute like `` is added, it also must be specified if the attribute should be visible to users or not. +When a new attribute like `` is added, it also must be specified if the attribute should be visible to users or not. ## Hide the attribute To hide the attribute: ```xml - + ``` ## Surface the attribute @@ -112,7 +131,7 @@ To hide the attribute: To surface the attribute: ```xml - + ``` Required metadata @@ -123,6 +142,6 @@ Optional metadata (note that if any metadata is set, `visible` is assumed to be - **type** - C# type to override missing type information from the manifest definition - **name** - The name of the managed attribute property if the default isn't correct -- **obsolete** - A string describing the reason for this member being `[Obsolete ("foo")]` -- **readonly** - Whether to generate the property with a `private set`, defaults to `false` -- **manualMap** - Whether to exclude the property from the `mapping` field used by `Xamarin.Android.Build.Tasks, defaults to `false` +- **obsolete** - A string describing the reason for this member being `[Obsolete ("reason")]` +- **readonly** - Whether to generate the property with a `private set`; defaults to `false` +- **manualMap** - Whether to exclude the property from the `mapping` field used by `Xamarin.Android.Build.Tasks`; defaults to `false` diff --git a/build-tools/manifest-attribute-codegen/SourceWriters/AttributeDataClass.cs b/build-tools/manifest-attribute-codegen/SourceWriters/AttributeDataClass.cs index 54b1f10825e..3ee9f349144 100644 --- a/build-tools/manifest-attribute-codegen/SourceWriters/AttributeDataClass.cs +++ b/build-tools/manifest-attribute-codegen/SourceWriters/AttributeDataClass.cs @@ -101,7 +101,7 @@ public override void WriteMembers (CodeWriter writer) manual_mapping_partial?.Write (writer); - writer.WriteLineNoIndent ("#endif"); + writer.WriteLineNoIndent ("#endif // XABT_MANIFEST_EXTENSIONS"); } } } diff --git a/build-tools/manifest-attribute-codegen/manifest-attribute-codegen.csproj b/build-tools/manifest-attribute-codegen/manifest-attribute-codegen.csproj index 0486f1e8aa1..a7d321b26a9 100644 --- a/build-tools/manifest-attribute-codegen/manifest-attribute-codegen.csproj +++ b/build-tools/manifest-attribute-codegen/manifest-attribute-codegen.csproj @@ -7,7 +7,7 @@ enable enable ..\..\bin\Build$(Configuration) - false + false @@ -28,10 +28,11 @@ <_ManifestAttributeCodeGen>..\..\bin\Build$(Configuration)\manifest-attribute-codegen.dll <_ConfigurationFile>$(MSBuildThisFileDirectory)metadata.xml <_RepositoryBaseDirectory>..\..\ + <_ManifestFile>$(MSBuildThisFileDirectory)manifest-definition.xml + Command=""$(DotNetPreviewTool)" "$(_ManifestAttributeCodeGen)" "-sdk-path=$(AndroidSdkFullPath)" -base-dir=$(_RepositoryBaseDirectory) "-metadata-file=$(_ConfigurationFile)" "-output-manifest=$(_ManifestFile)"" /> diff --git a/build-tools/manifest-attribute-codegen/manifest-definition.xml b/build-tools/manifest-attribute-codegen/manifest-definition.xml index 527b74f748e..085709f4e28 100644 --- a/build-tools/manifest-attribute-codegen/manifest-definition.xml +++ b/build-tools/manifest-attribute-codegen/manifest-definition.xml @@ -1,6 +1,5 @@ - - + @@ -10,8 +9,15 @@ - - + + + + + + + + + manifest @@ -62,8 +68,35 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + manifest @@ -75,8 +108,12 @@ + + + + - + manifest @@ -87,8 +124,12 @@ + + + + - + manifest @@ -97,14 +138,16 @@ - + manifest + + - + manifest @@ -112,25 +155,25 @@ - + manifest - + manifest - + application - + manifest @@ -142,15 +185,15 @@ - + manifest - + manifest - + application @@ -174,14 +217,18 @@ + + - + provider + + - + provider @@ -190,8 +237,9 @@ + - + application @@ -211,9 +259,12 @@ + + + - + application @@ -228,8 +279,9 @@ + - + application @@ -287,8 +339,19 @@ - - + + + + + + + + + + + + + application @@ -302,8 +365,11 @@ + + + - + application activity receiver @@ -316,7 +382,7 @@ - + activity receiver service @@ -327,12 +393,13 @@ + - + intent-filter - + intent-filter @@ -345,13 +412,16 @@ + + + - + intent-filter - + manifest @@ -364,23 +434,24 @@ - + compatible-screens - + + - + intent - + intent @@ -400,6 +471,7 @@ + @@ -414,13 +486,9 @@ - - - - - - - + + + manifest @@ -435,6 +503,7 @@ + manifest @@ -444,6 +513,7 @@ application + application @@ -459,5 +529,111 @@ uses-static-library + + application + + + + + + + + application + + + + + manifest + + + + + + attribution + + + + + + + + manifest + + + queries + + + + queries + + + queries + + + + application + + + processes + + + + + + + + processes + + + + processes + + + + + + + + + + application + + + + + application + activity + receiver + provider + service + + + + + + application + + + + + application + + + + + + application + + + + + + + + manifest + + + install-constraints + + - diff --git a/src/Mono.Android/Android.App/MetaDataAttribute.cs b/src/Mono.Android/Android.App/MetaDataAttribute.cs index b1d758a89fe..38e49f5e38e 100644 --- a/src/Mono.Android/Android.App/MetaDataAttribute.cs +++ b/src/Mono.Android/Android.App/MetaDataAttribute.cs @@ -50,5 +50,5 @@ static MetaDataAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS } diff --git a/src/Mono.Android/Android.App/PermissionAttribute.cs b/src/Mono.Android/Android.App/PermissionAttribute.cs index b3aa4cf7e3a..10c81b71899 100644 --- a/src/Mono.Android/Android.App/PermissionAttribute.cs +++ b/src/Mono.Android/Android.App/PermissionAttribute.cs @@ -86,5 +86,5 @@ static PermissionAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS } diff --git a/src/Mono.Android/Android.App/PermissionGroupAttribute.cs b/src/Mono.Android/Android.App/PermissionGroupAttribute.cs index ff083697a01..ad70dde0ab6 100644 --- a/src/Mono.Android/Android.App/PermissionGroupAttribute.cs +++ b/src/Mono.Android/Android.App/PermissionGroupAttribute.cs @@ -70,5 +70,5 @@ static PermissionGroupAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS } diff --git a/src/Mono.Android/Android.App/PermissionTreeAttribute.cs b/src/Mono.Android/Android.App/PermissionTreeAttribute.cs index b36131bdd1a..92446be062e 100644 --- a/src/Mono.Android/Android.App/PermissionTreeAttribute.cs +++ b/src/Mono.Android/Android.App/PermissionTreeAttribute.cs @@ -62,5 +62,5 @@ static PermissionTreeAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS } diff --git a/src/Mono.Android/Android.App/UsesConfigurationAttribute.cs b/src/Mono.Android/Android.App/UsesConfigurationAttribute.cs index 27ff2116ba1..e0f6801854a 100644 --- a/src/Mono.Android/Android.App/UsesConfigurationAttribute.cs +++ b/src/Mono.Android/Android.App/UsesConfigurationAttribute.cs @@ -70,5 +70,5 @@ static UsesConfigurationAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS } diff --git a/src/Mono.Android/Android.App/UsesFeatureAttribute.cs b/src/Mono.Android/Android.App/UsesFeatureAttribute.cs index 848abd93aa9..ae1ab8f2cf7 100644 --- a/src/Mono.Android/Android.App/UsesFeatureAttribute.cs +++ b/src/Mono.Android/Android.App/UsesFeatureAttribute.cs @@ -56,5 +56,5 @@ static UsesFeatureAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS } diff --git a/src/Mono.Android/Android.App/UsesLibraryAttribute.cs b/src/Mono.Android/Android.App/UsesLibraryAttribute.cs index 00361462c6c..ff33ca5b184 100644 --- a/src/Mono.Android/Android.App/UsesLibraryAttribute.cs +++ b/src/Mono.Android/Android.App/UsesLibraryAttribute.cs @@ -46,5 +46,5 @@ static UsesLibraryAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS } diff --git a/src/Mono.Android/Android.App/UsesPermissionAttribute.cs b/src/Mono.Android/Android.App/UsesPermissionAttribute.cs index 62cc0f433ad..9f82ff314e5 100644 --- a/src/Mono.Android/Android.App/UsesPermissionAttribute.cs +++ b/src/Mono.Android/Android.App/UsesPermissionAttribute.cs @@ -46,5 +46,5 @@ static UsesPermissionAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS } diff --git a/src/Mono.Android/Android.Content/GrantUriPermissionAttribute.cs b/src/Mono.Android/Android.Content/GrantUriPermissionAttribute.cs index 7185a789031..5421c56fee1 100644 --- a/src/Mono.Android/Android.Content/GrantUriPermissionAttribute.cs +++ b/src/Mono.Android/Android.Content/GrantUriPermissionAttribute.cs @@ -54,5 +54,5 @@ static GrantUriPermissionAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.cs index d818f2b3add..53156fc6a1c 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ActivityAttribute.cs @@ -441,5 +441,5 @@ static ActivityAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ApplicationAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ApplicationAttribute.cs index 38c9aeaf5a4..99e99e8bbcb 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ApplicationAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ApplicationAttribute.cs @@ -308,5 +308,5 @@ static ApplicationAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/InstrumentationAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/InstrumentationAttribute.cs index a80caf7893d..6eef48104e1 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.App/InstrumentationAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/InstrumentationAttribute.cs @@ -94,5 +94,5 @@ static InstrumentationAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/LayoutAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/LayoutAttribute.cs index fd41ef39b8d..4fe465c9fe2 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.App/LayoutAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/LayoutAttribute.cs @@ -70,5 +70,5 @@ static LayoutAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ServiceAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ServiceAttribute.cs index 1871978de39..a6bb02dc906 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.App/ServiceAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.App/ServiceAttribute.cs @@ -118,5 +118,5 @@ static ServiceAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.Content/BroadcastReceiverAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.Content/BroadcastReceiverAttribute.cs index fcdf109d6b8..38c5ea98c71 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.Content/BroadcastReceiverAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.Content/BroadcastReceiverAttribute.cs @@ -110,5 +110,5 @@ static BroadcastReceiverAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS } diff --git a/src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.cs b/src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.cs index ccd6f220801..deddf84d4bb 100644 --- a/src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.cs +++ b/src/Xamarin.Android.NamingCustomAttributes/Android.Content/ContentProviderAttribute.cs @@ -148,5 +148,5 @@ static ContentProviderAttribute () } static partial void AddManualMapping (); -#endif +#endif // XABT_MANIFEST_EXTENSIONS }