Skip to content

Commit 0c5b60d

Browse files
authored
[Mono.Android.dll] Fix [SupportedOSPlatform] warnings. (#8247)
Fixes: #7590 Fix the remaining `[SupportedOSPlatform]` warnings in manually bound code. Other issues we were previously seeing appear to have been a bug in earlier .NET 8 previews. In the simple cases, we just needed to add `[SupportedOSPlatform]` to our hand-written methods. For more complicated cases, we resolve the remaining CA1416 and CA1422 warnings by using `[SuppressMessage]`. Rationale: The constructors for [`java.lang.Boolean(boolean)`][0], [`java.lang.Integer(int)`][2], etc., were marked as `@Deprecated` in API-33, with a suggestion to instead use [`Booleal.valueOf(boolean)`][1], [`Integer.valueOf(int)`][3], etc. We *cannot* follow this advice in multiple places of our infrastructure, due to a desire to reduce JNI Global Reference (GREF) usage and preserve thread safety. Imagine that two threads execute the following code: using (var val = Java.Lang.Integer.ValueOf(42)) { val.FloatValue(); } Because we attempt to preserve object identity -- if multiple Java calls of `Integer.valueOf(42)` return the same instance, then multiple C# calls of `Integer.ValueOf(42)` should likewise return the same instance -- we may be dealing with mutable shared state! 1. Thread 1: calls C# `Integer.ValueOf(42)`, calls Java `Integer.valueOf(42)`, `Java.Lang.Integer` wrapper instance created and registered. 2. Thread 1: calls `val.FloatValue()` 3. Thread 2: calls `Integer.ValueOf(42)`, gets wrapper instance created in (1) 4. Thread 1: calls `val.Dispose()` 5. Thread 2: calls `val.FloatValue()`. This throws an `ObjectDisposedException`, because of (4). We thus have a conundrum: if we replace all usage of the e.g. `Integer(int)` constructor with calls to `Integer.ValueOf(int)`, *we can no longer* call `.Dispose()` on the value. This willl increase GREF usage, *but could be an overall improvement* as it may also result in fewer Java-side `Integer` instances being created. Without additional testing and microbenchmarks, it's hard to say which is actually "better". In the absense of such a micobenchmark, resolve some of the CA1416 and CA1422 warnings by using `[SuppressMessage]`. [0]: https://developer.android.com/reference/java/lang/Boolean#Boolean(boolean) [1]: https://developer.android.com/reference/java/lang/Boolean#valueOf(boolean) [2]: https://developer.android.com/reference/java/lang/Integer#Integer(int) [3]: https://developer.android.com/reference/java/lang/Integer#valueOf(int)
1 parent 98f2f81 commit 0c5b60d

File tree

15 files changed

+30
-5
lines changed

15 files changed

+30
-5
lines changed

src/Mono.Android/Android.Content/ContentValues.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ public short GetAsShort (string key)
119119

120120
static IntPtr id_put_Ljava_lang_String_Ljava_lang_Boolean_;
121121
[Register ("put", "(Ljava/lang/String;Ljava/lang/Boolean;)V", "")]
122+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
122123
public void Put (string key, bool value)
123124
{
124125
if (id_put_Ljava_lang_String_Ljava_lang_Boolean_ == IntPtr.Zero)
@@ -134,6 +135,7 @@ public void Put (string key, bool value)
134135

135136
static IntPtr id_put_Ljava_lang_String_Ljava_lang_Byte_;
136137
[Register ("put", "(Ljava/lang/String;Ljava/lang/Byte;)V", "")]
138+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
137139
public void Put (string key, sbyte value)
138140
{
139141
if (id_put_Ljava_lang_String_Ljava_lang_Byte_ == IntPtr.Zero)
@@ -149,6 +151,7 @@ public void Put (string key, sbyte value)
149151

150152
static IntPtr id_put_Ljava_lang_String_Ljava_lang_Short_;
151153
[Register ("put", "(Ljava/lang/String;Ljava/lang/Short;)V", "")]
154+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
152155
public void Put (string key, short value)
153156
{
154157
if (id_put_Ljava_lang_String_Ljava_lang_Short_ == IntPtr.Zero)
@@ -164,6 +167,7 @@ public void Put (string key, short value)
164167

165168
static IntPtr id_put_Ljava_lang_String_Ljava_lang_Integer_;
166169
[Register ("put", "(Ljava/lang/String;Ljava/lang/Integer;)V", "")]
170+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
167171
public void Put (string key, int value)
168172
{
169173
if (id_put_Ljava_lang_String_Ljava_lang_Integer_ == IntPtr.Zero)
@@ -179,6 +183,7 @@ public void Put (string key, int value)
179183

180184
static IntPtr id_put_Ljava_lang_String_Ljava_lang_Long_;
181185
[Register ("put", "(Ljava/lang/String;Ljava/lang/Long;)V", "")]
186+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
182187
public void Put (string key, long value)
183188
{
184189
if (id_put_Ljava_lang_String_Ljava_lang_Long_ == IntPtr.Zero)
@@ -194,6 +199,7 @@ public void Put (string key, long value)
194199

195200
static IntPtr id_put_Ljava_lang_String_Ljava_lang_Float_;
196201
[Register ("put", "(Ljava/lang/String;Ljava/lang/Float;)V", "")]
202+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
197203
public void Put (string key, float value)
198204
{
199205
if (id_put_Ljava_lang_String_Ljava_lang_Float_ == IntPtr.Zero)
@@ -209,6 +215,7 @@ public void Put (string key, float value)
209215

210216
static IntPtr id_put_Ljava_lang_String_Ljava_lang_Double_;
211217
[Register ("put", "(Ljava/lang/String;Ljava/lang/Double;)V", "")]
218+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
212219
public void Put (string key, double value)
213220
{
214221
if (id_put_Ljava_lang_String_Ljava_lang_Double_ == IntPtr.Zero)

src/Mono.Android/Android.Content/Context.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ public void StartActivity (Type type)
2020

2121
#if ANDROID_34
2222
// Add correctly enumified overloads
23+
[global::System.Runtime.Versioning.SupportedOSPlatformAttribute ("android26.0")]
2324
public Intent? RegisterReceiver (BroadcastReceiver? receiver, IntentFilter? filter, ReceiverFlags flags)
2425
=> RegisterReceiver (receiver, filter, (ActivityFlags)flags);
2526

27+
[global::System.Runtime.Versioning.SupportedOSPlatformAttribute ("android26.0")]
2628
public Intent? RegisterReceiver (BroadcastReceiver? receiver, IntentFilter? filter, string? broadcastPermission, Handler? scheduler, ReceiverFlags flags)
2729
=> RegisterReceiver (receiver, filter, broadcastPermission, scheduler, (ActivityFlags)flags);
2830
#endif

src/Mono.Android/Android.Media/AudioTrack.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ namespace Android.Media
44
{
55
public partial class AudioTrack
66
{
7+
[global::System.Runtime.Versioning.ObsoletedOSPlatform ("android26.0")]
78
[Obsolete ("ChannelConfiguration is obsolete. Please use another overload with ChannelOut instead")]
89
public AudioTrack ([global::Android.Runtime.GeneratedEnum] Android.Media.Stream streamType, int sampleRateInHz, [global::Android.Runtime.GeneratedEnum] Android.Media.ChannelConfiguration channelConfig, [global::Android.Runtime.GeneratedEnum] Android.Media.Encoding audioFormat, int bufferSizeInBytes, [global::Android.Runtime.GeneratedEnum] Android.Media.AudioTrackMode mode)
910
: this (streamType, sampleRateInHz, (ChannelOut) (int) channelConfig, audioFormat, bufferSizeInBytes, mode)
1011
{
1112
}
1213
#if ANDROID_9
14+
[global::System.Runtime.Versioning.ObsoletedOSPlatform ("android26.0")]
1315
[Obsolete ("ChannelConfiguration is obsolete. Please use another overload with ChannelOut instead")]
1416
public AudioTrack ([global::Android.Runtime.GeneratedEnum] Android.Media.Stream streamType, int sampleRateInHz, [global::Android.Runtime.GeneratedEnum] Android.Media.ChannelConfiguration channelConfig, [global::Android.Runtime.GeneratedEnum] Android.Media.Encoding audioFormat, int bufferSizeInBytes, [global::Android.Runtime.GeneratedEnum] Android.Media.AudioTrackMode mode, int sessionId)
1517
: this (streamType, sampleRateInHz, (ChannelOut) (int) channelConfig, audioFormat, bufferSizeInBytes, mode, sessionId)

src/Mono.Android/Android.OS/AsyncTask.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace Android.OS {
99

10+
[global::System.Runtime.Versioning.ObsoletedOSPlatform ("android30.0")]
1011
[Register ("android/os/AsyncTask", DoNotGenerateAcw=true)]
1112
public abstract class AsyncTask<TParams, TProgress, TResult> : AsyncTask {
1213

src/Mono.Android/Android.OS/Handler.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace Android.OS {
55

66
public partial class Handler {
77

8+
[global::System.Runtime.Versioning.ObsoletedOSPlatform ("android30.0")]
89
public Handler (Action<Message> handler)
910
: this (new ActionHandlerCallback (handler))
1011
{

src/Mono.Android/Android.OS/Vibrator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ namespace Android.OS {
66

77
public partial class Vibrator {
88

9+
[global::System.Runtime.Versioning.ObsoletedOSPlatform ("android31.0", "Use VibratorManager to retrieve the default system vibrator.")]
910
public static Vibrator? FromContext (Context context)
1011
{
1112
return context.GetSystemService (Context.VibratorService!) as Vibrator;

src/Mono.Android/Android.Runtime/AndroidEnvironment.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ static void NotifyTimeZoneChanged ()
237237
//
238238
// Rationale
239239
// No longer called by the indicated caller, however we keep it for backward compatibility.
240+
[global::System.Runtime.Versioning.ObsoletedOSPlatform ("android31.0")]
240241
static void GetDisplayDPI (out float x_dpi, out float y_dpi)
241242
{
242243
var wm = Application.Context.GetSystemService (Context.WindowService).JavaCast <IWindowManager> ();

src/Mono.Android/Android.Runtime/JavaObject.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace Android.Runtime {
55
[Register ("mono/android/runtime/JavaObject")]
66
internal sealed class JavaObject : Java.Lang.Object {
77

8+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
89
public static IntPtr GetHandle (object obj)
910
{
1011
if (obj == null)

src/Mono.Android/Android.Telecom/InCallService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ public abstract partial class InCallService : Android.App.Service
77
{
88
#if ANDROID_23
99
[Obsolete ("Incorrect enum parameter, use the overload that takes a CallAudioRoute parameter instead.")]
10+
[global::System.Runtime.Versioning.ObsoletedOSPlatform ("android34.0")]
1011
[global::System.Runtime.Versioning.SupportedOSPlatformAttribute ("android23.0")]
1112
public void SetAudioRoute ([global::Android.Runtime.GeneratedEnum] Android.Telecom.VideoQuality route)
1213
{

src/Mono.Android/Android.Telephony/CellInfo.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,23 @@ public partial class CellInfo {
1111

1212
static Delegate? cb_getCellIdentity;
1313
#pragma warning disable 0169
14+
[global::System.Runtime.Versioning.SupportedOSPlatform ("android28.0")]
1415
static Delegate GetGetCellIdentityHandler ()
1516
{
1617
if (cb_getCellIdentity == null)
1718
cb_getCellIdentity = JNINativeWrapper.CreateDelegate ((Func<IntPtr, IntPtr, IntPtr>) n_GetCellIdentity);
1819
return cb_getCellIdentity;
1920
}
2021

22+
[global::System.Runtime.Versioning.SupportedOSPlatform ("android28.0")]
2123
static IntPtr n_GetCellIdentity (IntPtr jnienv, IntPtr native__this)
2224
{
2325
var __this = global::Java.Lang.Object.GetObject<Android.Telephony.CellInfo> (jnienv, native__this, JniHandleOwnership.DoNotTransfer)!;
2426
return JNIEnv.ToLocalJniHandle (__this.CellIdentity);
2527
}
2628
#pragma warning restore 0169
2729

30+
[global::System.Runtime.Versioning.SupportedOSPlatform ("android28.0")]
2831
public unsafe virtual Android.Telephony.CellIdentity CellIdentity {
2932
// Metadata.xml XPath method reference: path="/api/package[@name='android.telephony']/class[@name='CellInfo']/method[@name='getCellIdentity' and count(parameter)=0]"
3033
[Register ("getCellIdentity", "()Landroid/telephony/CellIdentity;", "GetGetCellIdentityHandler", ApiSince = 30)]

0 commit comments

Comments
 (0)