Bug 58393 - Bundle.putByteArray signature takes an unsigned byte array
Summary: Bundle.putByteArray signature takes an unsigned byte array
Alias: None
Product: Android
Classification: Xamarin
Component: General ()
Version: 7.3 (15.2)
Hardware: PC Windows
: --- normal
Target Milestone: abi-break-future
Assignee: Jonathan Pryor
Depends on:
Reported: 2017-07-25 17:55 UTC by Scott Mertz
Modified: 2017-09-21 19:29 UTC (History)
3 users (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report for Bug 58393 on Developer Community or GitHub if you have new information to add and do not yet see a matching new report.

If the latest results still closely match this report, you can use the original description:

  • Export the original title and description: Developer Community HTML or GitHub Markdown
  • Copy the title and description into the new report. Adjust them to be up-to-date if needed.
  • Add your new information.

In special cases on GitHub you might also want the comments: GitHub Markdown with public comments

Related Links:

Description Scott Mertz 2017-07-25 17:55:32 UTC
Bundle.putByte correctly takes a signed byte (sbyte), but Bundle.putByteArray takes an unsigned byte array (byte[]).

Bundle b = new Bundle();
b.PutByte("key", -100);
b.PutByteArray("key", new sbyte[] { -100 }); // Fails to compile: Argument 2: cannot convert from 'sbyte[]' to 'byte[]'
Comment 1 Jon Douglas [MSFT] 2017-07-26 16:19:40 UTC
Here are the two definitions of these methods based on our API docs and Mono.Android.dll:

PutByte(String, SByte)

Inserts a byte value into the mapping of this Bundle, replacing any existing value for the given key.

PutByteArray(String, Byte[])

Inserts a byte array value into the mapping of this Bundle, replacing any existing value for the given key.


Given that Java's byte data type is an 8-bit signed two's complement integer, I would expect the PutByteArray method to also be a signed byte array in C#. Thus I am CONFIRMING this issue for consistency sake. There may be an internal reason that one of the Android engineers can answer further.

https://developer.android.com/reference/android/os/Bundle.html#putByte(java.lang.String, byte)

https://developer.android.com/reference/android/os/Bundle.html#putByteArray(java.lang.String, byte[])




Thank you for the report!
Comment 2 Jonathan Pryor 2017-09-21 19:29:37 UTC
This is not going to be fixed anytime soon.

There are 201 methods in API-26 which return a `byte[]`, and 364 methods which take a `byte[]` parameter (which may or may not overlap with the 201 which return a `byte[]`).

This may or may not sound like much, but there's another, *more* important, number: 51 of these methods are `non-virtual`, meaning 313 methods are `virtual`. That raises a very significant problem in our current binding system:

1. We want to maintain API stability. 32 of these methods are on interfaces. We *cannot* change those. (Changing interfaces is *bad*.)

2. Virtual methods can be overridden, and our binding infrastructure will do unknowable things if a class declares two virtual methods which bind the same Java method:

  partial class Intent {
    [Register ("putExtra", ...)]
    public virtual unsafe Intent PutExtra (string name, byte[] value);

    [Register ("putExtra", ...)]
    public virtual unsafe Intent PutExtra (string name, sbyte[] value);

That may look fine, but if a derived class overrides both of those methods, which should get invoked? They're the same Java method; There Can Be Only One™ override. Even if a class *doesn't* override both classes, the question remains: our current binding infrastructure can't handle this scenario.

In short, a global search-and-replace of `byte[]` with `sbyte[]` isn't going to happen. It has the potential to break too much. Selective overloads of existing methods with `sbyte[]` parameters *could* happen, but only if those methods are non-virtual (all 51 of them!).

A complete fix of this bug is nigh impossible without an ABI break. We have some ideas for a new API, but those all involve requiring C#8, so even if we pursue that idea, it won't see the light of day anytime soon.

Leaving this bug open if only to track the underlying idea.