locked
NullPointerException when transferring byte array over IPC using AIDL RRS feed

  • Question

  • User145697 posted

    I have a Java service that I'm binding to using Xamarin using AIDL and there seems to be a bug in the generated code that is causing me a problem.

    The problem is that if the AIDL contains a method that takes an in byte[] or an inout byte[] parameter, a NullPointerException is raised.

    I have tracked it down to the following generated code:

    protected override bool OnTransact(int code, global::Android.OS.Parcel data, global::Android.OS.Parcel reply, int flags)
        {
            switch (code)
            {
                case global::Android.OS.BinderConsts.InterfaceTransaction:
                    reply.WriteString(descriptor);
                    return true;
    
                case TransactionOnDecodeComplete:
                    {
                        data.EnforceInterface(descriptor);
                        int arg0 = default(int);
                        arg0 = data.ReadInt();
                        int arg1 = default(int);
                        arg1 = data.ReadInt();
                        byte[] arg2 = default(byte[]);
                        data.ReadByteArray(arg2);
                        this.OnDecodeComplete(arg0, arg1, arg2);
                        reply.WriteNoException();
                        data.WriteInt(arg0);
                        data.WriteInt(arg1);
                        data.WriteByteArray(arg2);
                        return true;
                    }
            }
            return base.OnTransact(code, data, reply, flags);
        }
    

    The problem is that arg2 is initialised to default(byte[]) which is null. It is then passed to Parcel.ReadByteArray which, according to the documentation cannot be null because it copies the data into the given array.

    Is this a bug and, if so, is there a way to work around the problem?

    Monday, August 3, 2015 11:04 AM

Answers

  • User145697 posted

    I've fixed this by overriding the method in the binder class, copying the generated method contents from the stub file and changing the two lines:

    byte[] arg2 = default(byte[]);
    data.ReadByteArray(arg2);
    

    to be:

    byte[] arg2 = data.CreateByteArray();
    

    This then also failed but I changed the method to be in instead of inout which removed the line data.WriteByteArray(arg2); from the generated code which I also removed from my copy and everything worked from then on.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Tuesday, August 4, 2015 1:32 PM

All replies

  • User145697 posted

    I've fixed this by overriding the method in the binder class, copying the generated method contents from the stub file and changing the two lines:

    byte[] arg2 = default(byte[]);
    data.ReadByteArray(arg2);
    

    to be:

    byte[] arg2 = data.CreateByteArray();
    

    This then also failed but I changed the method to be in instead of inout which removed the line data.WriteByteArray(arg2); from the generated code which I also removed from my copy and everything worked from then on.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Tuesday, August 4, 2015 1:32 PM
  • User67095 posted

    Stumbled upon this same issue. Reported on Bugzilla: https://bugzilla.xamarin.com/show_bug.cgi?id=34825

    Tuesday, October 13, 2015 5:14 PM
  • User67095 posted

    I can confirm that the fix proposed above by @SteveKaye does work

    Wednesday, October 14, 2015 7:55 AM
  • User67095 posted

    It's really unfortunate the fix is still not on the latest release. It's been 7 months and every time I change my AIDL file, I still have to fix it by hand. :(

    Tuesday, May 24, 2016 5:31 PM
  • User67095 posted

    Looks like I already had the fix but it doesn't work... :(

    The latest version (Xamarin.Android 6.1.1.1) generates the following code:

    byte [] arg0 = default (byte []);
    arg0 = data.CreateByteArray (); data.ReadByteArray (arg0);
    

    and then I get:

    Java.Lang.RuntimeException: bad array length
    

    If I replace the generated code again by the code proposed above by @SteveKaye :

    byte[] arg0 = data.CreateByteArray();
    

    The documentation for CreateByteArray() states:

    Read and return a byte[] object from the parcel.
    

    So the ReadByteArray() call is unnecessary.

    Friday, June 24, 2016 3:17 PM
  • User240271 posted

    Hi, @AntaoAlmada.I got the same issue when transferring byte array over IPC by using AIDL.Would I need using the old xamarin version?

    Thursday, July 28, 2016 1:39 PM