Skip to content

Commit

Permalink
[AndroidManifest] Add Android.App.PropertyAttribute (dotnet#9016)
Browse files Browse the repository at this point in the history
Fixes: dotnet#8729

API-31 added support for a [`<property/>`][0] element within
`AndroidManifest.xml`, which can be contained within `<activity/>`, 
`<application/>`, `<provider/>`, `<receiver/>`, and `<service/>`
elements.

Add a new `Android.App.PropertyAttribute` custom attribute which will
emit `<property/>` within `AndroidManifest.xml`:

	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class,
	        AllowMultiple = true, Inherited = false)]
	public partial class PropertyAttribute : Attribute {

	    public string Name      {get;}
	    public string? Resource {get;}
	    public string? Value    {get;}

	    public PropertyAttribute (string name);
	}

Semantics otherwise appear to be identical to
`<meta-data/>`/`MetaDataAttribute`: only `Resource` or `Value` can
be specified, etc.  (This is checked by `aapt2`.)

Using `[assembly:Property(…)]` will result in `<property/>` being
emitted within the `<application/>` element.

For example:

	[Service (Name = "fooService", ForegroundServiceType = Android.Content.PM.ForegroundService.TypeSpecialUse)]
	[Property ("android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE", Value = "explanation_for_special_use")]
	public partial class FooService : Service {
	}

will emit the `AndroidManifest.xml` fragment:

	<service android:name="fooService" android:foregroundServiceType="specialUse">
	  <property
	      android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
	      android:value="explanation_for_special_use"
	  />
	</service>

[0]: https://developer.android.com/guide/topics/manifest/property-element
  • Loading branch information
jpobst authored Jul 10, 2024
1 parent 8c4b353 commit 3ab04df
Show file tree
Hide file tree
Showing 11 changed files with 312 additions and 13 deletions.
20 changes: 20 additions & 0 deletions build-tools/manifest-attribute-codegen/manifest-definition.xml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
<a name='resetEnabledSettingsOnAppDataCleared' format='boolean' api-level='33' />
<a name='knownActivityEmbeddingCerts' api-level='33' />
<a name='enableOnBackInvokedCallback' format='boolean' api-level='33' />
<a name='allowCrossUidActivitySwitchFromBelow' format='boolean' api-level='35' />
</e>
<e name='permission' api-level='10'>
<parent>manifest</parent>
Expand Down Expand Up @@ -219,6 +220,7 @@
<a name='splitName' api-level='26' />
<a name='forceUriPermissions' api-level='29' />
<a name='attributionTags' api-level='31' />
<a name='systemUserOnly' format='boolean' api-level='35' />
</e>
<e name='grant-uri-permission' api-level='10'>
<parent>provider</parent>
Expand Down Expand Up @@ -263,6 +265,7 @@
<a name='foregroundServiceType' api-level='29' />
<a name='attributionTags' api-level='31' />
<a name='allowSharedIsolatedProcess' format='boolean' api-level='34' />
<a name='systemUserOnly' format='boolean' api-level='35' />
</e>
<e name='receiver' api-level='10'>
<parent>application</parent>
Expand Down Expand Up @@ -350,6 +353,7 @@
<a name='knownActivityEmbeddingCerts' api-level='33' />
<a name='requiredDisplayCategory' format='string' api-level='34' />
<a name='enableOnBackInvokedCallback' format='boolean' api-level='34' />
<a name='requireContentUriPermissionFromCaller' format='string' api-level='35' />
</e>
<e name='activity-alias' api-level='10'>
<parent>application</parent>
Expand Down Expand Up @@ -416,6 +420,16 @@
<a name='sspAdvancedPattern' format='string' api-level='31' />
<a name='sspSuffix' format='string' api-level='31' />
<a name='pathSuffix' api-level='31' />
<a name='query' format='string' api-level='35' />
<a name='queryPrefix' format='string' api-level='35' />
<a name='queryPattern' format='string' api-level='35' />
<a name='queryAdvancedPattern' format='string' api-level='35' />
<a name='querySuffix' format='string' api-level='35' />
<a name='fragment' format='string' api-level='35' />
<a name='fragmentPrefix' format='string' api-level='35' />
<a name='fragmentPattern' format='string' api-level='35' />
<a name='fragmentAdvancedPattern' format='string' api-level='35' />
<a name='fragmentSuffix' format='string' api-level='35' />
</e>
<e name='category' api-level='10'>
<parent>intent-filter</parent>
Expand Down Expand Up @@ -580,6 +594,7 @@
<a name='memtagMode' api-level='31' />
<a name='nativeHeapZeroInitialized' api-level='31' />
<a name='name' api-level='33' />
<a name='useEmbeddedDex' api-level='35' />
</e>
<e name='deny-permission' api-level='30'>
<parent>processes</parent>
Expand Down Expand Up @@ -620,6 +635,7 @@
<a name='name' api-level='33' />
<a name='versionMajor' format='integer' api-level='33' />
<a name='certDigest' format='string' api-level='33' />
<a name='optional' format='boolean' api-level='35' />
</e>
<e name='apex-system-service' api-level='33'>
<parent>application</parent>
Expand All @@ -636,4 +652,8 @@
<parent>install-constraints</parent>
<a name='value' api-level='34' />
</e>
<e name='uri-relative-filter-group' api-level='35'>
<parent>intent-filter</parent>
<a name='allow' format='boolean' api-level='35' />
</e>
</m>
12 changes: 11 additions & 1 deletion build-tools/manifest-attribute-codegen/metadata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<type name="permission" namespace="Android.App" outputFile="src\Mono.Android\Android.App\PermissionAttribute.cs" usage="AttributeTargets.Assembly" allowMultiple="true" />
<type name="permission-group" namespace="Android.App" outputFile="src\Mono.Android\Android.App\PermissionGroupAttribute.cs" usage="AttributeTargets.Assembly" allowMultiple="true" />
<type name="permission-tree" namespace="Android.App" outputFile="src\Mono.Android\Android.App\PermissionTreeAttribute.cs" usage="AttributeTargets.Assembly" />
<type name="property" namespace="Android.App" outputFile="src\Mono.Android\Android.App\PropertyAttribute.cs" usage="AttributeTargets.Assembly | AttributeTargets.Class" allowMultiple="true" defaultConstructor="false" />
<type name="uses-configuration" namespace="Android.App" outputFile="src\Mono.Android\Android.App\UsesConfigurationAttribute.cs" usage="AttributeTargets.Assembly" allowMultiple="true" />
<type name="uses-feature" namespace="Android.App" outputFile="src\Mono.Android\Android.App\UsesFeatureAttribute.cs" usage="AttributeTargets.Assembly" allowMultiple="true" />
<type name="uses-library" namespace="Android.App" outputFile="src\Mono.Android\Android.App\UsesLibraryAttribute.cs" usage="AttributeTargets.Assembly | AttributeTargets.Class" allowMultiple="true" />
Expand Down Expand Up @@ -49,7 +50,6 @@
<type name="process" ignore="true" />
<type name="processes" ignore="true" />
<type name="profileable" ignore="true" />
<type name="property" ignore="true" />
<type name="protected-broadcast" ignore="true" />
<type name="public-key" ignore="true" />
<type name="queries" ignore="true" />
Expand All @@ -65,6 +65,7 @@
<type name="supports-input-input-type" ignore="true" />
<type name="supports-screens" ignore="true" />
<type name="upgrade-key-set" ignore="true" />
<type name="uri-relative-filter-group" ignore="true" />
<type name="uses-native-library" ignore="true" />
<type name="uses-package" ignore="true" />
<type name="uses-sdk" ignore="true" />
Expand Down Expand Up @@ -121,6 +122,7 @@
<element path="activity.requiredDisplayCategory" visible="false" />
<element path="activity.recreateOnConfigChanges" type="Android.Content.PM.ConfigChanges" />
<element path="activity.relinquishTaskIdentity" type="bool" />
<element path="activity.requireContentUriPermissionFromCaller" visible="false" />
<element path="activity.resizeableActivity" type="bool" />
<element path="activity.resumeWhilePausing" type="bool" />
<element path="activity.rotationAnimation" type="Android.Views.WindowRotationAnimation" />
Expand All @@ -147,6 +149,7 @@
<element path="application.allowBackup" type="bool" />
<element path="application.allowClearUserData" type="bool" />
<element path="application.allowClearUserDataOnFailedRestore" visible="false" />
<element path="application.allowCrossUidActivitySwitchFromBelow" visible="false" />
<element path="application.allowNativeHeapPointerTagging" visible="false" />
<element path="application.allowTaskReparenting" type="bool" />
<element path="application.appCategory" visible="false" />
Expand Down Expand Up @@ -303,6 +306,11 @@
<element path="permission-tree.name" visible="true" />
<element path="permission-tree.roundIcon" visible="true" />

<!-- <property> -->
<element path="property.name" type="string" readonly="true" />
<element path="property.resource" visible="true" />
<element path="property.value" visible="true" />

<!-- <provider> -->
<element path="provider.attributionTags" visible="false" />
<element path="provider.authorities" type="string[]" readonly="true" manualMap="true" />
Expand All @@ -326,6 +334,7 @@
<element path="provider.singleUser" visible="false" />
<element path="provider.splitName" visible="false" />
<element path="provider.syncable" type="bool" />
<element path="provider.systemUserOnly" visible="false" />
<element path="provider.visibleToInstantApps" visible="false" />
<element path="provider.writePermission" visible="true" />

Expand Down Expand Up @@ -366,6 +375,7 @@
<element path="service.singleUser" visible="false" />
<element path="service.splitName" visible="false" />
<element path="service.stopWithTask" visible="false" />
<element path="service.systemUserOnly" visible="false" />
<element path="service.useAppZygote" visible="false" />
<element path="service.visibleToInstantApps" visible="false" />

Expand Down
11 changes: 11 additions & 0 deletions src/Mono.Android/Android.App/PropertyAttribute.Partial.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;

namespace Android.App;

public sealed partial class PropertyAttribute
{
public PropertyAttribute (string name)
{
Name = name;
}
}
54 changes: 54 additions & 0 deletions src/Mono.Android/Android.App/PropertyAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------

#nullable enable

using System;

namespace Android.App;

[Serializable]
[AttributeUsage (AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public sealed partial class PropertyAttribute : Attribute {
public string Name { get; private set; }

public string? Resource { get; set; }

public string? Value { get; set; }

#if XABT_MANIFEST_EXTENSIONS
static Xamarin.Android.Manifest.ManifestDocumentElement<PropertyAttribute> mapping = new ("property");

static PropertyAttribute ()
{
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 // XABT_MANIFEST_EXTENSIONS
}
2 changes: 2 additions & 0 deletions src/Mono.Android/Mono.Android.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
</Compile>
<Compile Include="Android.App\IntentFilterAttribute.Partial.cs" />
<Compile Include="Android.App\MetaDataAttribute.Partial.cs" />
<Compile Include="Android.App\PropertyAttribute.Partial.cs" />
<Compile Include="Android.App\UsesFeatureAttribute.Partial.cs" />
<Compile Include="Android.App\UsesLibraryAttribute.Partial.cs" />
<Compile Include="Android.App\UsesPermissionAttribute.Partial.cs" />
Expand Down Expand Up @@ -152,6 +153,7 @@
<Compile Include="Android.App\PermissionGroupAttribute.cs" />
<Compile Include="Android.App\PermissionTreeAttribute.cs" />
<Compile Include="Android.App\ProgressDialog.cs" />
<Compile Include="Android.App\PropertyAttribute.cs" />
<Compile Include="Android.App\SearchManager.cs" />
<Compile Include="Android.App\SupportsGLTextureAttribute.cs" />
<Compile Include="Android.App\SyncContext.cs" />
Expand Down
7 changes: 7 additions & 0 deletions src/Mono.Android/PublicAPI/API-35/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,13 @@ Android.App.Notification.TvExtender.TvExtender(Android.App.Notification! notif)
Android.App.NotificationChannel.VibrationEffect.get -> Android.OS.VibrationEffect?
Android.App.NotificationChannel.VibrationEffect.set -> void
Android.App.PictureInPictureUiState.IsTransitioningToPip.get -> bool
Android.App.PropertyAttribute
Android.App.PropertyAttribute.Name.get -> string!
Android.App.PropertyAttribute.PropertyAttribute(string! name) -> void
Android.App.PropertyAttribute.Resource.get -> string?
Android.App.PropertyAttribute.Resource.set -> void
Android.App.PropertyAttribute.Value.get -> string?
Android.App.PropertyAttribute.Value.set -> void
Android.App.SdkSandbox.AppOwnedSdkSandboxInterface
Android.App.SdkSandbox.AppOwnedSdkSandboxInterface.AppOwnedSdkSandboxInterface(string! name, long version, Android.OS.IBinder! binder) -> void
Android.App.SdkSandbox.AppOwnedSdkSandboxInterface.DescribeContents() -> int
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Mono.Cecil;

using Java.Interop.Tools.Cecil;

using Xamarin.Android.Manifest;

namespace Android.App {

partial class PropertyAttribute {

ICollection<string> specified;

public static IEnumerable<PropertyAttribute> FromCustomAttributeProvider (ICustomAttributeProvider type, TypeDefinitionCache cache)
{
IEnumerable<CustomAttribute> attrs = type.GetCustomAttributes ("Android.App.PropertyAttribute");
if (!attrs.Any ())
yield break;
foreach (CustomAttribute attr in attrs) {
var self = new PropertyAttribute ((string) attr.ConstructorArguments [0].Value);
self.specified = mapping.Load (self, attr, cache);
self.specified.Add ("Name");
yield return self;
}
}

public XElement ToElement (string packageName, TypeDefinitionCache cache)
{
return mapping.ToElement (this, specified, packageName, cache);
}
}
}
Loading

0 comments on commit 3ab04df

Please sign in to comment.