Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Xamarin..Android.Tools.Aidl] inout+inout array Parameters (#5726)
Fixes: #4717 Fixes: #5079 Context: https://cs.android.com/android/platform/superproject/+/af1f0005723416a36e025fded7eccb2fd8c777de:system/tools/aidl/generate_java_binder.cpp;l=358 Context: https://cs.android.com/android/platform/superproject/+/af1f0005723416a36e025fded7eccb2fd8c777de:system/tools/aidl/generate_java_binder.cpp;l=486 Context: https://cs.android.com/android/platform/superproject/+/af1f0005723416a36e025fded7eccb2fd8c777de:system/tools/aidl/generate_java_binder.cpp;l=646 `Xamarin.Android.Tools.Aidl.CSharpCodeGenerator` did not properly support `inout` or `out` parameter marshaling of array types. For `inout` arrays: // AIDL interface Test { void inoutArray (inout byte [] args); } the emitted `OnTransact()` method needs to write the "output" value to the `reply` parameter, *not* the `data` parameter: // generated C# public interface ITest : Android.OS.IInterface { void InoutArray (byte[] args) } abstract partial class ITestStub : Binder, ITest { protected override bool OnTransact (int code, Parcel data, Parcel reply, int flags) { switch (code) { case TransactionInoutArray: { data.EnforceInterface (descriptor); byte [] arg0 = default (byte []); arg0 = data.CreateStringArray (); this.InoutArray (arg0); reply.WriteNoException (); data.WriteByteArray (arg0); // SHOULD USE `reply`, not `data`! return true; } } } } Similar-yet-more-so, with `out` array parameters: // AIDL interface Test { void outArray (out byte [] args); } the `OnTransact()` method *also* needs to support `args` being `null`: // generated C# public interface ITest : global::Android.OS.IInterface { void OutArray (byte[] args) } abstract partial class ITestStub : Binder, ITest { protected override bool OnTransact (int code, Parcel data, Parcel reply, int flags) { switch (code) { case TransactionOutArray: { data.EnforceInterface (descriptor); byte [] arg0 = default (byte []); int arg0_length = data.ReadInt(); // NEEDED if (arg0_length < 0) { // NEEDED arg0 = null; // NEEDED } // NEEDED else { // NEEDED arg0 = new byte [arg0_length]; // NEEDED } // NEEDED this.OutArray (arg0); reply.WriteNoException (); reply.WriteByteArray (arg0); // PREVIOUSLY used data, not reply! return true; } } } } *Plus* the `Proxy` implementation needs to support `null`: partial class ITestStub { public class Proxy : Java.Lang.Object, ITest { public void OutArray (byte[] args) { var __data = Parcel.Obtain (); var __reply = Parcel.Obtain (); try { __data.WriteInterfaceToken (descriptor); if (args == null) { // NEEDED __data.WriteInt (-1); // NEEDED } else { // NEEDED __data.WriteInt(args.Length); // NEEDED } // NEEDED remote.Transact (ITestStub.TransactionOutArray, __data, __reply, 0); … } } } This is comparable to the Java code the Android Studio produces.
- Loading branch information