-
Notifications
You must be signed in to change notification settings - Fork 101
Concierge
The CMSDK consumer library is built as a static jar, so any consumer of it can end up in a scenario where their client (apk) is utilizing a protocol that is either newer or older than what is supported by the framework in CyanogenMod on whatever device they're running on.
This variance can happen after any release, our clients may end up sending us marshalled data that is either longer than expected or shorter than expected which may cause object corruption when attempting to recreate the custom parcelable utilizing the common CREATOR pattern in android.
To work around this you need to inject parcel headers as per the example of DashClock by Roman Nurik.
To inject the parcel header, Concierge writes a few items in the first few datapositions of the Parcel, most notably, it writes the PARCELABLE_VERSION:
// Write parcelable version, make sure to define explicit changes
// within {@link #PARCELABLE_VERSION);
mParcel.writeInt(mParcelableVersion);
// Inject a placeholder that will store the parcel size from this point on
// (not including the size itself).
mSizePosition = parcel.dataPosition();
mParcel.writeInt(0);
mStartPosition = parcel.dataPosition();
To inversely read it, Concierge fetches the parcelable version for you by reading the injected header and providing you a simple interface to fetch it through.
mParcel = parcel;
// Read {@link #PARCELABLE_VERSION) from the header
mParcelableVersion = parcel.readInt();
// Get the size
mParcelableSize = parcel.readInt();
// Get the expected start position per parcel nesting
mStartPosition = parcel.dataPosition();
Since Concierge handles your parcels and makes sure they get marshalled and unmarshalled correctly when cross IPC boundaries even when there is a version mismatch between the client sdk level and the framework implementation, there is only the responsibility of decrementing from latest to earliest release within your parceling.
On incoming parcel (to be unmarshalled):
ParcelInfo incomingParcelInfo = Concierge.receiveParcel(incomingParcel);
int parcelableVersion = incomingParcelInfo.getParcelVersion();
// Do unmarshalling steps here iterating over every plausible version
// Complete the process
incomingParcelInfo.complete();
On outgoing parcel (to be marshalled):
ParcelInfo outgoingParcelInfo = Concierge.prepareParcel(incomingParcel);
// Do marshalling steps here iterating over every plausible version
// Complete the process
outgoingParcelInfo.complete();