androidipcparcelableaidl

android AIDL interface, parcelables and backwards compatibility


We expose an AIDL service to third party developers. We'd like to return parcelable objects from this service, but we have concerns about backwards compatibility. By this, I mean clients compiled against version N of the parcelable, and a service compiled against version N+1 must work together.

From my tests, for simple flat objects (simple type fields only), backwards compatibility is possible, as long as new fields are parceled at the end of stream ... e.g.,

in.writeInt(field1);
in.writeInt(field2); // new field

however, when it comes to complex objects, things blow up. for example,

class D implements Parcelable {
  int field1;
}

class C implements Parcelable {
  List<D> ds;
}

if a second field is added to class D,

class D implements Parcelable {
  int field1;
  int field2; // new field
}

unmarshalling of class Cs fail (i tried using Parcel.writeList() and Parcel.writeParcelableArray()).

This seems almost inconceivable that this case can't be handled. Sure, we can leave the old binder interface as-is, and create a new binder interface that returns objects of the new class with the additional fields, but for a service that returns oft-changing classes, this will result in a convoluted mess. For example, interface 1.0 returns a Person. now we add a field, and we have a new binder interface 2.0 that returns Person2 objects, and so on.

This leaves us to using some more forgiving format, like JSON, to pass IPC data.

Any suggestions?


Solution

  • Clients compiled against version N of the Parcelable and the AIDL interface will need to be supported by the Service until the heat death of the universe, not just until N+1, unless you want to break a bunch of clients or are in position to force those developers to update their apps.

    Sure, we can leave the old binder interface as-is

    Any change to the AIDL itself means that you need a new service endpoint for the new protocol version, let alone changes to the Parcelable definitions.

    for example, interface 1.0 returns a Person. now we add a field, and we have a new binder interface 2.0 that returns Person2 objects, and so on.

    Either:

    Your alternative of JSON is roughly analogous to using a Bundle in the first place, except that you don't have to fuss with your own marshaling/unmarshaling code with a Bundle.

    Parcelable specifically avoids versioning for speed reasons. That's why Parceable is not designed for durable storage, when classes might change between when the data was saved and when the data was read in.