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

+7
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

+2
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

+2
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

+1
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

+1
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

+1
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

+1
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

+1
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

+1
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

+3
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)]

src/Mono.Android/Android.Views/View.cs

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public void UnscheduleDrawable (Android.Graphics.Drawables.Drawable who, Action
7777

7878
#if ANDROID_11
7979
[Obsolete ("Please Use DispatchSystemUiVisibilityChanged(SystemUiFlags)")]
80+
[global::System.Runtime.Versioning.ObsoletedOSPlatform ("android30.0")]
8081
public void DispatchSystemUiVisibilityChanged (int visibility)
8182
{
8283
DispatchSystemUiVisibilityChanged ((SystemUiFlags) visibility);

src/Mono.Android/Java.Interop/JavaConvert.cs

+2
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ static Func<IntPtr, JniHandleOwnership, object> GetJniHandleConverterForType ([D
274274
return Convert.ChangeType (value, targetType, CultureInfo.InvariantCulture);
275275
}
276276

277+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
277278
static Dictionary<Type, Func<object, IJavaObject>> JavaObjectConverters = new Dictionary<Type, Func<object, IJavaObject>>() {
278279
{ typeof (bool), value => new Java.Lang.Boolean ((bool) value) },
279280
{ typeof (byte), value => new Java.Lang.Byte ((sbyte) (byte) value) },
@@ -306,6 +307,7 @@ static Func<IntPtr, JniHandleOwnership, object> GetJniHandleConverterForType ([D
306307
return new Android.Runtime.JavaObject (value);
307308
}
308309

310+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
309311
static Dictionary<Type, Func<object, IntPtr>> LocalJniHandleConverters = new Dictionary<Type, Func<object, IntPtr>> {
310312
{ typeof (bool), value => {
311313
using (var v = new Java.Lang.Boolean ((bool) value))

src/Mono.Android/Java.Interop/TypeManager.cs

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using Java.Interop.Tools.TypeNameMappings;
99

1010
using Android.Runtime;
11-
using System.Diagnostics.CodeAnalysis;
1211

1312
namespace Java.Interop {
1413

src/Mono.Android/Java.Lang/Object.cs

+7
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ protected void SetHandle (IntPtr value, JniHandleOwnership transfer)
316316
return new Java.Lang.Object (JNIEnv.NewArray (value), JniHandleOwnership.TransferLocalRef);
317317
}
318318

319+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
319320
public static implicit operator Java.Lang.Object (bool value)
320321
{
321322
return new Java.Lang.Boolean (value);
@@ -327,11 +328,13 @@ public static implicit operator Java.Lang.Object (byte value)
327328
throw new InvalidOperationException ("Should not be reached");
328329
}
329330

331+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
330332
public static implicit operator Java.Lang.Object (sbyte value)
331333
{
332334
return new Java.Lang.Byte (value);
333335
}
334336

337+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
335338
public static implicit operator Java.Lang.Object (char value)
336339
{
337340
return new Java.Lang.Character (value);
@@ -343,6 +346,7 @@ public static implicit operator Java.Lang.Object (uint value)
343346
throw new InvalidOperationException ("Should not be reached");
344347
}
345348

349+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
346350
public static implicit operator Java.Lang.Object (int value)
347351
{
348352
return new Java.Lang.Integer (value);
@@ -354,16 +358,19 @@ public static implicit operator Java.Lang.Object (ulong value)
354358
throw new InvalidOperationException ("Should not be reached");
355359
}
356360

361+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
357362
public static implicit operator Java.Lang.Object (long value)
358363
{
359364
return new Java.Lang.Long (value);
360365
}
361366

367+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
362368
public static implicit operator Java.Lang.Object (float value)
363369
{
364370
return new Java.Lang.Float (value);
365371
}
366372

373+
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Interoperability", "CA1422:Validate platform compatibility", Justification = "Suggested replacement uses instance sharing")]
367374
public static implicit operator Java.Lang.Object (double value)
368375
{
369376
return new Java.Lang.Double (value);

src/Mono.Android/Mono.Android.csproj

-4
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,6 @@
4242
<NoWarn>$(NoWarn);CS1572;CS1573;CS1574;CS1584;CS1587;CS1591;CS1658;</NoWarn>
4343
</PropertyGroup>
4444

45-
<PropertyGroup Condition=" '$(_EnableCodeAnalyzerPlatformWarnings)' == '' ">
46-
<NoWarn>$(NoWarn);CA1422;CA1416</NoWarn>
47-
</PropertyGroup>
48-
4945
<ItemGroup>
5046
<AdditionalFiles Include="PublicAPI\API-$(AndroidApiLevel)\PublicAPI.Shipped.txt" />
5147
<AdditionalFiles Include="PublicAPI\API-$(AndroidApiLevel)\PublicAPI.Unshipped.txt" />

0 commit comments

Comments
 (0)