Skip to content

Commit

Permalink
[Mono.Android] Fix Context.RegisterReceiver() enumification (#7735)
Browse files Browse the repository at this point in the history
Fixes: #7503

Context: e33eb53
Context: df6c716
Context: 76ab8b2

The bindings for
[`Context.registerReceiver(BroadcastReceiver, IntentFilter, int)`][0]
and related overloads incorrectly enumified the `int` parameter as
the `Android.Content.ActivityFlags` enum (e33eb53), when it should
have been `Android.Content.ReceiverFlags` (df6c716).

Unfortunately we can't directly fix this, as the bound
`Context.RegisterReceiver(BroadcastReceiver, IntentFilter, ActivityFlags)`
method is *`abstract`*, and thus changing it would break compatibility.

Fix this without breaking API by:

 1. Creating new overload methods which chain to the existing methods
 2. Mark the existing methods and method overrides as `[Obsolete]`.

a'la:

	partial class Context {
	    [Obsolete ("This method has an incorrect enumeration type. Use the overload that takes ReceiverFlags instead.")]
	    public abstract Intent? RegisterReceiver (BroadcastReceiver? receiver, IntentFilter? filter, [GeneratedEnum] ActivityFlags flags);

	    public Intent? RegisterReceiver (BroadcastReceiver? receiver, IntentFilter? filter, ReceiverFlags flags) =>
	        RegisterReceiver (receiver, filter, (ActivityFlags)flags);
	}

A concern with this approach is that it means that a public `abstract`
method is now `[Obsolete]`, which would make it "weird" to override.
However, this is a method that should *never* be overridden by user
code, so we think this is an acceptable compromise.

Additionally, it was noticed that the public API tracking added in
76ab8b2 did not flag this change as an error, only a warning.
Convert the RS0016 and RS0017 warnings into errors to ensure that any
new public API is accounted for.

[0]: https://developer.android.com/reference/android/content/Context#registerReceiver(android.content.BroadcastReceiver,%20android.content.IntentFilter,%20int)
  • Loading branch information
jpobst committed Jul 25, 2023
1 parent 805872b commit d9e4407
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/Mono.Android/Android.Content/Context.cs
@@ -1,4 +1,5 @@
using System;
using Android.OS;
using Android.Runtime;

namespace Android.Content {
Expand All @@ -16,5 +17,14 @@ public void StartActivity (Type type)
[Obsolete ("This constant will be removed in the future version. Use Android.Content.ReceiverFlags enum directly instead of this field.")]
public const int ReceiverVisibleToInstantApps = 1;
#endif

#if ANDROID_34
// Add correctly enumified overloads
public Intent? RegisterReceiver (BroadcastReceiver? receiver, IntentFilter? filter, ReceiverFlags flags)
=> RegisterReceiver (receiver, filter, (ActivityFlags)flags);

public Intent? RegisterReceiver (BroadcastReceiver? receiver, IntentFilter? filter, string? broadcastPermission, Handler? scheduler, ReceiverFlags flags)
=> RegisterReceiver (receiver, filter, broadcastPermission, scheduler, (ActivityFlags)flags);
#endif
}
}
5 changes: 5 additions & 0 deletions src/Mono.Android/Mono.Android.csproj
Expand Up @@ -27,7 +27,12 @@
<PropertyGroup>
<DefineConstants Condition=" '$(AndroidApiLevel)' &gt; '$(AndroidLatestStableApiLevel)' ">$(DefineConstants);ANDROID_UNSTABLE</DefineConstants>
<OutputPath>$(_MonoAndroidNETDefaultOutDir)</OutputPath>

<!-- Allow PublicApiAnalyzers to be turned off -->
<RunAnalyzers Condition=" '$(DisableApiCompatibilityCheck)' == 'True' ">false</RunAnalyzers>

<!-- PublicApiAnalyzers warnings should be errors, but building in VS throws incorrect extra warnings -->
<WarningsAsErrors Condition=" '$(BuildingInsideVisualStudio)' != 'True' ">$(WarningsAsErrors);RS0016,RS0017</WarningsAsErrors>
</PropertyGroup>

<PropertyGroup Condition=" '$(IncludeAndroidJavadoc)' == 'True' ">
Expand Down
2 changes: 2 additions & 0 deletions src/Mono.Android/PublicAPI/API-34/PublicAPI.Unshipped.txt
Expand Up @@ -8448,6 +8448,8 @@ Android.Content.Context.ObtainStyledAttributes(Android.Util.IAttributeSet? set,
Android.Content.Context.ObtainStyledAttributes(Android.Util.IAttributeSet? set, int[]! attrs, int defStyleAttr, int defStyleRes) -> Android.Content.Res.TypedArray!
Android.Content.Context.ObtainStyledAttributes(int resid, int[]! attrs) -> Android.Content.Res.TypedArray!
Android.Content.Context.ObtainStyledAttributes(int[]! attrs) -> Android.Content.Res.TypedArray!
Android.Content.Context.RegisterReceiver(Android.Content.BroadcastReceiver? receiver, Android.Content.IntentFilter? filter, Android.Content.ReceiverFlags flags) -> Android.Content.Intent?
Android.Content.Context.RegisterReceiver(Android.Content.BroadcastReceiver? receiver, Android.Content.IntentFilter? filter, string? broadcastPermission, Android.OS.Handler? scheduler, Android.Content.ReceiverFlags flags) -> Android.Content.Intent?
Android.Content.Context.StartActivity(System.Type! type) -> void
Android.Content.ContextParams
Android.Content.ContextParams.AttributionTag.get -> string?
Expand Down
8 changes: 8 additions & 0 deletions src/Mono.Android/metadata
Expand Up @@ -1809,6 +1809,14 @@

<!-- 2 conflicting copies of ErrorEventArgs -->
<attr api-since="34" path="/api/package[@name='android.speech']/interface[@name='ModelDownloadListener']/method[@name='onError' and count(parameter)=1 and parameter[1][@type='int']]" name="argsType">ModelDownloadErrorEventArgs</attr>

<!-- Fix some incorrectly enumified methods -->
<attr api-since="34" path="/api/package[@name='android.content']/class[@name='Context']/method[@name='registerReceiver' and count(parameter)=3 and parameter[1][@type='android.content.BroadcastReceiver'] and parameter[2][@type='android.content.IntentFilter'] and parameter[3][@type='int']]" name="deprecated">This method has an incorrect enumeration type. Use the overload that takes ReceiverFlags instead.</attr>
<attr api-since="34" path="/api/package[@name='android.content']/class[@name='Context']/method[@name='registerReceiver' and count(parameter)=5 and parameter[1][@type='android.content.BroadcastReceiver'] and parameter[2][@type='android.content.IntentFilter'] and parameter[3][@type='java.lang.String'] and parameter[4][@type='android.os.Handler'] and parameter[5][@type='int']]" name="deprecated">This method has an incorrect enumeration type. Use the overload that takes ReceiverFlags instead.</attr>
<attr api-since="34" path="/api/package[@name='android.content']/class[@name='ContextWrapper']/method[@name='registerReceiver' and count(parameter)=3 and parameter[1][@type='android.content.BroadcastReceiver'] and parameter[2][@type='android.content.IntentFilter'] and parameter[3][@type='int']]" name="deprecated">This method has an incorrect enumeration type. Use the overload that takes ReceiverFlags instead.</attr>
<attr api-since="34" path="/api/package[@name='android.content']/class[@name='ContextWrapper']/method[@name='registerReceiver' and count(parameter)=5 and parameter[1][@type='android.content.BroadcastReceiver'] and parameter[2][@type='android.content.IntentFilter'] and parameter[3][@type='java.lang.String'] and parameter[4][@type='android.os.Handler'] and parameter[5][@type='int']]" name="deprecated">This method has an incorrect enumeration type. Use the overload that takes ReceiverFlags instead.</attr>
<attr api-since="34" path="/api/package[@name='android.test.mock']/class[@name='MockContext']/method[@name='registerReceiver' and count(parameter)=3 and parameter[1][@type='android.content.BroadcastReceiver'] and parameter[2][@type='android.content.IntentFilter'] and parameter[3][@type='int']]" name="deprecated">This method has an incorrect enumeration type. Use the overload that takes ReceiverFlags instead.</attr>
<attr api-since="34" path="/api/package[@name='android.test.mock']/class[@name='MockContext']/method[@name='registerReceiver' and count(parameter)=5 and parameter[1][@type='android.content.BroadcastReceiver'] and parameter[2][@type='android.content.IntentFilter'] and parameter[3][@type='java.lang.String'] and parameter[4][@type='android.os.Handler'] and parameter[5][@type='int']]" name="deprecated">This method has an incorrect enumeration type. Use the overload that takes ReceiverFlags instead.</attr>

<!--
***********************************************************************
Expand Down

0 comments on commit d9e4407

Please sign in to comment.