From 33a24ad5890b3244bbb91fd4286ecd9ee682b273 Mon Sep 17 00:00:00 2001 From: Adnan Begovic Date: Mon, 20 Jul 2015 13:47:50 -0700 Subject: [PATCH] cmsdk: Declare a parcelable header. - This change forces that a parcelable header is written as the first data positions in a parcel and defines a means to distinguish between old sdk class versions vs new ones to do proper unraveling of parcels. Ticket: BAMBOO-152 Change-Id: I9cc762fe8a51cc527e85be7fe5de57e4613be019 --- src/java/cyanogenmod/app/CustomTile.java | 157 +++++++++++++---- src/java/cyanogenmod/app/Profile.java | 160 ++++++++++++------ src/java/cyanogenmod/app/ProfileGroup.java | 54 ++++-- .../app/StatusBarPanelCustomTile.java | 89 ++++++++-- src/java/cyanogenmod/os/Build.java | 10 ++ .../profiles/AirplaneModeSettings.java | 37 +++- .../profiles/BrightnessSettings.java | 37 +++- .../profiles/ConnectionSettings.java | 39 ++++- .../profiles/RingModeSettings.java | 37 +++- .../cyanogenmod/profiles/StreamSettings.java | 39 ++++- 10 files changed, 535 insertions(+), 124 deletions(-) diff --git a/src/java/cyanogenmod/app/CustomTile.java b/src/java/cyanogenmod/app/CustomTile.java index bda1afa3..3578a668 100644 --- a/src/java/cyanogenmod/app/CustomTile.java +++ b/src/java/cyanogenmod/app/CustomTile.java @@ -23,6 +23,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import cyanogenmod.os.Build; import java.util.ArrayList; @@ -85,26 +86,42 @@ public class CustomTile implements Parcelable { * Unflatten the CustomTile from a parcel. */ public CustomTile(Parcel parcel) { - resourcesPackageName = parcel.readString(); - if (parcel.readInt() != 0) { - this.onClick = PendingIntent.CREATOR.createFromParcel(parcel); - } - if (parcel.readInt() != 0) { - this.onSettingsClick = Intent.CREATOR.createFromParcel(parcel); - } - if (parcel.readInt() != 0) { - this.onClickUri = Uri.CREATOR.createFromParcel(parcel); - } - if (parcel.readInt() != 0) { - this.label = parcel.readString(); - } - if (parcel.readInt() != 0) { - this.contentDescription = parcel.readString(); + // Read parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + int parcelableVersion = parcel.readInt(); + int parcelableSize = parcel.readInt(); + int startPosition = parcel.dataPosition(); + + // Pattern here is that all new members should be added to the end of + // the writeToParcel method. Then we step through each version, until the latest + // API release to help unravel this parcel + if (parcelableVersion >= Build.CM_VERSION_CODES.APRICOT) { + if (parcel.readInt() != 0) { + this.onClick = PendingIntent.CREATOR.createFromParcel(parcel); + } + if (parcel.readInt() != 0) { + this.onSettingsClick = Intent.CREATOR.createFromParcel(parcel); + } + if (parcel.readInt() != 0) { + this.onClickUri = Uri.CREATOR.createFromParcel(parcel); + } + if (parcel.readInt() != 0) { + this.label = parcel.readString(); + } + if (parcel.readInt() != 0) { + this.contentDescription = parcel.readString(); + } + if (parcel.readInt() != 0) { + this.expandedStyle = ExpandedStyle.CREATOR.createFromParcel(parcel); + } + this.icon = parcel.readInt(); } - if (parcel.readInt() != 0) { - this.expandedStyle = ExpandedStyle.CREATOR.createFromParcel(parcel); + + if (parcelableVersion >= Build.CM_VERSION_CODES.BOYSENBERRY) { + this.resourcesPackageName = parcel.readString(); } - this.icon = parcel.readInt(); + + parcel.setDataPosition(startPosition + parcelableSize); } /** @@ -177,7 +194,17 @@ public int describeContents() { @Override public void writeToParcel(Parcel out, int flags) { - out.writeString(resourcesPackageName); + // Write parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + out.writeInt(Build.PARCELABLE_VERSION); + + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + int sizePosition = out.dataPosition(); + out.writeInt(0); + int startPosition = out.dataPosition(); + + // ==== APRICOT ===== if (onClick != null) { out.writeInt(1); onClick.writeToParcel(out, 0); @@ -215,6 +242,15 @@ public void writeToParcel(Parcel out, int flags) { out.writeInt(0); } out.writeInt(icon); + + // ==== BOYSENBERRY ===== + out.writeString(resourcesPackageName); + + // Go back and write size + int parcelableSize = out.dataPosition() - startPosition; + out.setDataPosition(sizePosition); + out.writeInt(parcelableSize); + out.setDataPosition(startPosition + parcelableSize); } /** @@ -245,10 +281,23 @@ private ExpandedStyle() { private int styleId; private ExpandedStyle(Parcel parcel) { - if (parcel.readInt() != 0) { - expandedItems = parcel.createTypedArray(ExpandedItem.CREATOR); + // Read parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + int parcelableVersion = parcel.readInt(); + int parcelableSize = parcel.readInt(); + int startPosition = parcel.dataPosition(); + + // Pattern here is that all new members should be added to the end of + // the writeToParcel method. Then we step through each version, until the latest + // API release to help unravel this parcel + if (parcelableVersion >= Build.CM_VERSION_CODES.APRICOT) { + if (parcel.readInt() != 0) { + expandedItems = parcel.createTypedArray(ExpandedItem.CREATOR); + } + styleId = parcel.readInt(); } - styleId = parcel.readInt(); + + parcel.setDataPosition(startPosition + parcelableSize); } /** @@ -298,6 +347,17 @@ public int describeContents() { @Override public void writeToParcel(Parcel parcel, int i) { + // Write parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + parcel.writeInt(Build.PARCELABLE_VERSION); + + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + int sizePosition = parcel.dataPosition(); + parcel.writeInt(0); + int startPosition = parcel.dataPosition(); + + // ==== APRICOT ==== if (expandedItems != null) { parcel.writeInt(1); parcel.writeTypedArray(expandedItems, 0); @@ -305,6 +365,12 @@ public void writeToParcel(Parcel parcel, int i) { parcel.writeInt(0); } parcel.writeInt(styleId); + + // Go back and write size + int parcelableSize = parcel.dataPosition() - startPosition; + parcel.setDataPosition(sizePosition); + parcel.writeInt(parcelableSize); + parcel.setDataPosition(startPosition + parcelableSize); } @Override @@ -444,16 +510,29 @@ protected void internalSetOnClickPendingIntent(PendingIntent pendingIntent) { * Unflatten the ExpandedItem from a parcel. */ protected ExpandedItem(Parcel parcel) { - if (parcel.readInt() != 0) { - onClickPendingIntent = PendingIntent.CREATOR.createFromParcel(parcel); - } - if (parcel.readInt() != 0) { - itemTitle = parcel.readString(); - } - if (parcel.readInt() != 0) { - itemSummary = parcel.readString(); + // Read parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + int parcelableVersion = parcel.readInt(); + int parcelableSize = parcel.readInt(); + int startPosition = parcel.dataPosition(); + + // Pattern here is that all new members should be added to the end of + // the writeToParcel method. Then we step through each version, until the latest + // API release to help unravel this parcel + if (parcelableVersion >= Build.CM_VERSION_CODES.APRICOT) { + if (parcel.readInt() != 0) { + onClickPendingIntent = PendingIntent.CREATOR.createFromParcel(parcel); + } + if (parcel.readInt() != 0) { + itemTitle = parcel.readString(); + } + if (parcel.readInt() != 0) { + itemSummary = parcel.readString(); + } + itemDrawableResourceId = parcel.readInt(); } - itemDrawableResourceId = parcel.readInt(); + + parcel.setDataPosition(startPosition + parcelableSize); } @Override @@ -463,6 +542,16 @@ public int describeContents() { @Override public void writeToParcel(Parcel out, int flags) { + // Write parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + out.writeInt(Build.PARCELABLE_VERSION); + + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + int sizePosition = out.dataPosition(); + out.writeInt(0); + int startPosition = out.dataPosition(); + if (onClickPendingIntent != null) { out.writeInt(1); onClickPendingIntent.writeToParcel(out, 0); @@ -482,6 +571,12 @@ public void writeToParcel(Parcel out, int flags) { out.writeInt(0); } out.writeInt(itemDrawableResourceId); + + // Go back and write size + int parcelableSize = out.dataPosition() - startPosition; + out.setDataPosition(sizePosition); + out.writeInt(parcelableSize); + out.setDataPosition(startPosition + parcelableSize); } @Override diff --git a/src/java/cyanogenmod/app/Profile.java b/src/java/cyanogenmod/app/Profile.java index 18e95947..5e4964b7 100755 --- a/src/java/cyanogenmod/app/Profile.java +++ b/src/java/cyanogenmod/app/Profile.java @@ -26,6 +26,7 @@ import android.text.TextUtils; import android.util.Log; +import cyanogenmod.os.Build; import cyanogenmod.profiles.AirplaneModeSettings; import cyanogenmod.profiles.BrightnessSettings; import cyanogenmod.profiles.ConnectionSettings; @@ -189,18 +190,47 @@ public ProfileTrigger(int type, String id, int state, String name) { } private ProfileTrigger(Parcel in) { - mType = in.readInt(); - mId = in.readString(); - mState = in.readInt(); - mName = in.readString(); + // Read parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + int parcelableVersion = in.readInt(); + int parcelableSize = in.readInt(); + int startPosition = in.dataPosition(); + + // Pattern here is that all new members should be added to the end of + // the writeToParcel method. Then we step through each version, until the latest + // API release to help unravel this parcel + if (parcelableVersion >= Build.CM_VERSION_CODES.BOYSENBERRY) { + mType = in.readInt(); + mId = in.readString(); + mState = in.readInt(); + mName = in.readString(); + } + + in.setDataPosition(startPosition + parcelableSize); } @Override public void writeToParcel(Parcel dest, int flags) { + // Write parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + dest.writeInt(Build.PARCELABLE_VERSION); + + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + int sizePosition = dest.dataPosition(); + dest.writeInt(0); + int startPosition = dest.dataPosition(); + dest.writeInt(mType); dest.writeString(mId); dest.writeInt(mState); dest.writeString(mName); + + // Go back and write size + int parcelableSize = dest.dataPosition() - startPosition; + dest.setDataPosition(sizePosition); + dest.writeInt(parcelableSize); + dest.setDataPosition(startPosition + parcelableSize); } @Override @@ -476,6 +506,17 @@ public int describeContents() { /** @hide */ @Override public void writeToParcel(Parcel dest, int flags) { + // Write parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + dest.writeInt(Build.PARCELABLE_VERSION); + + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + int sizePosition = dest.dataPosition(); + dest.writeInt(0); + int startPosition = dest.dataPosition(); + + // === BOYSENBERRY === if (!TextUtils.isEmpty(mName)) { dest.writeInt(1); dest.writeString(mName); @@ -550,62 +591,81 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeMap(mTriggers); dest.writeInt(mExpandedDesktopMode); dest.writeInt(mDozeMode); + + // Go back and write size + int parcelableSize = dest.dataPosition() - startPosition; + dest.setDataPosition(sizePosition); + dest.writeInt(parcelableSize); + dest.setDataPosition(startPosition + parcelableSize); } /** @hide */ public void readFromParcel(Parcel in) { - if (in.readInt() != 0) { - mName = in.readString(); - } - if (in.readInt() != 0) { - mNameResId = in.readInt(); - } - if (in.readInt() != 0) { - mUuid = ParcelUuid.CREATOR.createFromParcel(in).getUuid(); - } - if (in.readInt() != 0) { - for (Parcelable parcel : in.readParcelableArray(null)) { - ParcelUuid u = (ParcelUuid) parcel; - mSecondaryUuids.add(u.getUuid()); + // Read parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + int parcelableVersion = in.readInt(); + int parcelableSize = in.readInt(); + int startPosition = in.dataPosition(); + + // Pattern here is that all new members should be added to the end of + // the writeToParcel method. Then we step through each version, until the latest + // API release to help unravel this parcel + if (parcelableVersion >= Build.CM_VERSION_CODES.BOYSENBERRY) { + if (in.readInt() != 0) { + mName = in.readString(); } - } - mStatusBarIndicator = (in.readInt() == 1); - mProfileType = in.readInt(); - mDirty = (in.readInt() == 1); - if (in.readInt() != 0) { - for (Parcelable group : in.readParcelableArray(null)) { - ProfileGroup grp = (ProfileGroup) group; - profileGroups.put(grp.getUuid(), grp); - if (grp.isDefaultGroup()) { - mDefaultGroup = grp; + if (in.readInt() != 0) { + mNameResId = in.readInt(); + } + if (in.readInt() != 0) { + mUuid = ParcelUuid.CREATOR.createFromParcel(in).getUuid(); + } + if (in.readInt() != 0) { + for (Parcelable parcel : in.readParcelableArray(null)) { + ParcelUuid u = (ParcelUuid) parcel; + mSecondaryUuids.add(u.getUuid()); } } - } - if (in.readInt() != 0) { - for (Parcelable parcel : in.readParcelableArray(null)) { - StreamSettings stream = (StreamSettings) parcel; - streams.put(stream.getStreamId(), stream); + mStatusBarIndicator = (in.readInt() == 1); + mProfileType = in.readInt(); + mDirty = (in.readInt() == 1); + if (in.readInt() != 0) { + for (Parcelable group : in.readParcelableArray(null)) { + ProfileGroup grp = (ProfileGroup) group; + profileGroups.put(grp.getUuid(), grp); + if (grp.isDefaultGroup()) { + mDefaultGroup = grp; + } + } } - } - if (in.readInt() != 0) { - for (Parcelable parcel : in.readParcelableArray(null)) { - ConnectionSettings connection = (ConnectionSettings) parcel; - connections.put(connection.getConnectionId(), connection); + if (in.readInt() != 0) { + for (Parcelable parcel : in.readParcelableArray(null)) { + StreamSettings stream = (StreamSettings) parcel; + streams.put(stream.getStreamId(), stream); + } } + if (in.readInt() != 0) { + for (Parcelable parcel : in.readParcelableArray(null)) { + ConnectionSettings connection = (ConnectionSettings) parcel; + connections.put(connection.getConnectionId(), connection); + } + } + if (in.readInt() != 0) { + mRingMode = RingModeSettings.CREATOR.createFromParcel(in); + } + if (in.readInt() != 0) { + mAirplaneMode = AirplaneModeSettings.CREATOR.createFromParcel(in); + } + if (in.readInt() != 0) { + mBrightness = BrightnessSettings.CREATOR.createFromParcel(in); + } + mScreenLockMode = in.readInt(); + in.readMap(mTriggers, null); + mExpandedDesktopMode = in.readInt(); + mDozeMode = in.readInt(); } - if (in.readInt() != 0) { - mRingMode = RingModeSettings.CREATOR.createFromParcel(in); - } - if (in.readInt() != 0) { - mAirplaneMode = AirplaneModeSettings.CREATOR.createFromParcel(in); - } - if (in.readInt() != 0) { - mBrightness = BrightnessSettings.CREATOR.createFromParcel(in); - } - mScreenLockMode = in.readInt(); - in.readMap(mTriggers, null); - mExpandedDesktopMode = in.readInt(); - mDozeMode = in.readInt(); + + in.setDataPosition(startPosition + parcelableSize); } /** diff --git a/src/java/cyanogenmod/app/ProfileGroup.java b/src/java/cyanogenmod/app/ProfileGroup.java index 3403172c..5109e9d5 100644 --- a/src/java/cyanogenmod/app/ProfileGroup.java +++ b/src/java/cyanogenmod/app/ProfileGroup.java @@ -18,6 +18,7 @@ import android.app.Notification; import android.app.NotificationGroup; +import cyanogenmod.os.Build; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -263,32 +264,61 @@ public int describeContents() { /** @hide */ @Override public void writeToParcel(Parcel dest, int flags) { + // Write parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + dest.writeInt(Build.PARCELABLE_VERSION); + + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + int sizePosition = dest.dataPosition(); + dest.writeInt(0); + int startPosition = dest.dataPosition(); + + // === BOYSENBERRY === dest.writeString(mName); new ParcelUuid(mUuid).writeToParcel(dest, 0); dest.writeInt(mDefaultGroup ? 1 : 0); dest.writeInt(mDirty ? 1 : 0); dest.writeParcelable(mSoundOverride, flags); dest.writeParcelable(mRingerOverride, flags); - dest.writeString(mSoundMode.name()); dest.writeString(mRingerMode.name()); dest.writeString(mVibrateMode.name()); dest.writeString(mLightsMode.name()); + + // Go back and write size + int parcelableSize = dest.dataPosition() - startPosition; + dest.setDataPosition(sizePosition); + dest.writeInt(parcelableSize); + dest.setDataPosition(startPosition + parcelableSize); } /** @hide */ public void readFromParcel(Parcel in) { - mName = in.readString(); - mUuid = ParcelUuid.CREATOR.createFromParcel(in).getUuid(); - mDefaultGroup = in.readInt() != 0; - mDirty = in.readInt() != 0; - mSoundOverride = in.readParcelable(null); - mRingerOverride = in.readParcelable(null); - - mSoundMode = Mode.valueOf(Mode.class, in.readString()); - mRingerMode = Mode.valueOf(Mode.class, in.readString()); - mVibrateMode = Mode.valueOf(Mode.class, in.readString()); - mLightsMode = Mode.valueOf(Mode.class, in.readString()); + // Read parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + int parcelableVersion = in.readInt(); + int parcelableSize = in.readInt(); + int startPosition = in.dataPosition(); + + // Pattern here is that all new members should be added to the end of + // the writeToParcel method. Then we step through each version, until the latest + // API release to help unravel this parcel + if (parcelableVersion >= Build.CM_VERSION_CODES.BOYSENBERRY) { + mName = in.readString(); + mUuid = ParcelUuid.CREATOR.createFromParcel(in).getUuid(); + mDefaultGroup = in.readInt() != 0; + mDirty = in.readInt() != 0; + mSoundOverride = in.readParcelable(null); + mRingerOverride = in.readParcelable(null); + + mSoundMode = Mode.valueOf(Mode.class, in.readString()); + mRingerMode = Mode.valueOf(Mode.class, in.readString()); + mVibrateMode = Mode.valueOf(Mode.class, in.readString()); + mLightsMode = Mode.valueOf(Mode.class, in.readString()); + } + + in.setDataPosition(startPosition + parcelableSize); } public enum Mode { diff --git a/src/java/cyanogenmod/app/StatusBarPanelCustomTile.java b/src/java/cyanogenmod/app/StatusBarPanelCustomTile.java index 1e111d63..b686e3b4 100644 --- a/src/java/cyanogenmod/app/StatusBarPanelCustomTile.java +++ b/src/java/cyanogenmod/app/StatusBarPanelCustomTile.java @@ -19,6 +19,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; +import cyanogenmod.os.Build; /** * Class encapsulating a Custom Tile. Sent by the StatusBarManagerService to clients including @@ -66,21 +67,62 @@ public StatusBarPanelCustomTile(String pkg, String resPkg, String opPkg, int id, public StatusBarPanelCustomTile(Parcel in) { - this.pkg = in.readString(); - this.resPkg = in.readString(); - this.opPkg = in.readString(); - this.id = in.readInt(); - if (in.readInt() != 0) { - this.tag = in.readString(); - } else { - this.tag = null; + // Read parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + int parcelableVersion = in.readInt(); + int parcelableSize = in.readInt(); + int startPosition = in.dataPosition(); + + // tmp variables for final + String tmpResPkg = null; + String tmpPkg = null; + String tmpOpPkg = null; + int tmpId = -1; + String tmpTag = null; + int tmpUid = -1; + int tmpPid = -1; + CustomTile tmpCustomTile = null; + UserHandle tmpUser = null; + long tmpPostTime = -1; + + // Pattern here is that all new members should be added to the end of + // the writeToParcel method. Then we step through each version, until the latest + // API release to help unravel this parcel + if (parcelableVersion >= Build.CM_VERSION_CODES.APRICOT) { + // default + tmpPkg = in.readString(); + tmpOpPkg = in.readString(); + tmpId = in.readInt(); + if (in.readInt() != 0) { + tmpTag = in.readString(); + } else { + tmpTag = null; + } + tmpUid = in.readInt(); + tmpPid = in.readInt(); + tmpCustomTile = new CustomTile(in); + tmpUser = UserHandle.readFromParcel(in); + tmpPostTime = in.readLong(); } - this.uid = in.readInt(); - this.initialPid = in.readInt(); - this.customTile = new CustomTile(in); - this.user = UserHandle.readFromParcel(in); - this.postTime = in.readLong(); + + if (parcelableVersion >= Build.CM_VERSION_CODES.BOYSENBERRY) { + tmpResPkg = in.readString(); + } + + // Assign finals + this.resPkg = tmpResPkg; + this.pkg = tmpPkg; + this.opPkg = tmpOpPkg; + this.id = tmpId; + this.tag = tmpTag; + this.uid = tmpUid; + this.initialPid = tmpPid; + this.customTile = tmpCustomTile; + this.user = tmpUser; + this.postTime = tmpPostTime; this.key = key(); + + in.setDataPosition(startPosition + parcelableSize); } private String key() { @@ -115,8 +157,18 @@ public int describeContents() { @Override public void writeToParcel(Parcel out, int flags) { + // Write parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + out.writeInt(Build.PARCELABLE_VERSION); + + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + int sizePosition = out.dataPosition(); + out.writeInt(0); + int startPosition = out.dataPosition(); + + // ==== APRICOT === out.writeString(this.pkg); - out.writeString(this.resPkg); out.writeString(this.opPkg); out.writeInt(this.id); if (this.tag != null) { @@ -130,6 +182,15 @@ public void writeToParcel(Parcel out, int flags) { this.customTile.writeToParcel(out, flags); user.writeToParcel(out, flags); out.writeLong(this.postTime); + + // ==== BOYSENBERRY ===== + out.writeString(this.resPkg); + + // Go back and write size + int parcelableSize = out.dataPosition() - startPosition; + out.setDataPosition(sizePosition); + out.writeInt(parcelableSize); + out.setDataPosition(startPosition + parcelableSize); } @Override diff --git a/src/java/cyanogenmod/os/Build.java b/src/java/cyanogenmod/os/Build.java index b1f4cd4b..7d5422e8 100644 --- a/src/java/cyanogenmod/os/Build.java +++ b/src/java/cyanogenmod/os/Build.java @@ -27,6 +27,16 @@ public class Build { /** Value used for when a build property is unknown. */ public static final String UNKNOWN = "unknown"; + /** + * Since there might be a case where new versions of the cm framework use applications running + * old versions of the protocol (and thus old versions of this class), we need a versioning + * system for the parcels sent between the core framework and its sdk users. + * + * This parcelable version should be the latest version API version listed in + * {@link CM_VERSION_CODES} + */ + public static final int PARCELABLE_VERSION = CM_VERSION_CODES.BOYSENBERRY; + private static final SparseArray sdkMap; static { diff --git a/src/java/cyanogenmod/profiles/AirplaneModeSettings.java b/src/java/cyanogenmod/profiles/AirplaneModeSettings.java index 563e2974..f79bf844 100644 --- a/src/java/cyanogenmod/profiles/AirplaneModeSettings.java +++ b/src/java/cyanogenmod/profiles/AirplaneModeSettings.java @@ -22,6 +22,7 @@ import android.os.Parcel; import android.os.Parcelable; +import cyanogenmod.os.Build; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -187,15 +188,45 @@ public int describeContents() { /** @hide */ @Override public void writeToParcel(Parcel dest, int flags) { + // Write parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + dest.writeInt(Build.PARCELABLE_VERSION); + + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + int sizePosition = dest.dataPosition(); + dest.writeInt(0); + int startPosition = dest.dataPosition(); + + // === BOYSENBERRY === dest.writeInt(mOverride ? 1 : 0); dest.writeInt(mValue); dest.writeInt(mDirty ? 1 : 0); + + // Go back and write size + int parcelableSize = dest.dataPosition() - startPosition; + dest.setDataPosition(sizePosition); + dest.writeInt(parcelableSize); + dest.setDataPosition(startPosition + parcelableSize); } /** @hide */ public void readFromParcel(Parcel in) { - mOverride = in.readInt() != 0; - mValue = in.readInt(); - mDirty = in.readInt() != 0; + // Read parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + int parcelableVersion = in.readInt(); + int parcelableSize = in.readInt(); + int startPosition = in.dataPosition(); + + // Pattern here is that all new members should be added to the end of + // the writeToParcel method. Then we step through each version, until the latest + // API release to help unravel this parcel + if (parcelableVersion >= Build.CM_VERSION_CODES.BOYSENBERRY) { + mOverride = in.readInt() != 0; + mValue = in.readInt(); + mDirty = in.readInt() != 0; + } + + in.setDataPosition(startPosition + parcelableSize); } } diff --git a/src/java/cyanogenmod/profiles/BrightnessSettings.java b/src/java/cyanogenmod/profiles/BrightnessSettings.java index c0b94383..eb744916 100644 --- a/src/java/cyanogenmod/profiles/BrightnessSettings.java +++ b/src/java/cyanogenmod/profiles/BrightnessSettings.java @@ -21,6 +21,7 @@ import android.os.Parcel; import android.os.Parcelable; +import cyanogenmod.os.Build; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -185,15 +186,45 @@ public int describeContents() { /** @hide */ @Override public void writeToParcel(Parcel dest, int flags) { + // Write parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + dest.writeInt(Build.PARCELABLE_VERSION); + + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + int sizePosition = dest.dataPosition(); + dest.writeInt(0); + int startPosition = dest.dataPosition(); + + // === BOYSENBERRY === dest.writeInt(mOverride ? 1 : 0); dest.writeInt(mValue); dest.writeInt(mDirty ? 1 : 0); + + // Go back and write size + int parcelableSize = dest.dataPosition() - startPosition; + dest.setDataPosition(sizePosition); + dest.writeInt(parcelableSize); + dest.setDataPosition(startPosition + parcelableSize); } /** @hide */ public void readFromParcel(Parcel in) { - mOverride = in.readInt() != 0; - mValue = in.readInt(); - mDirty = in.readInt() != 0; + // Read parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + int parcelableVersion = in.readInt(); + int parcelableSize = in.readInt(); + int startPosition = in.dataPosition(); + + // Pattern here is that all new members should be added to the end of + // the writeToParcel method. Then we step through each version, until the latest + // API release to help unravel this parcel + if (parcelableVersion >= Build.CM_VERSION_CODES.BOYSENBERRY) { + mOverride = in.readInt() != 0; + mValue = in.readInt(); + mDirty = in.readInt() != 0; + } + + in.setDataPosition(startPosition + parcelableSize); } } diff --git a/src/java/cyanogenmod/profiles/ConnectionSettings.java b/src/java/cyanogenmod/profiles/ConnectionSettings.java index 61ad6b93..f8f745df 100644 --- a/src/java/cyanogenmod/profiles/ConnectionSettings.java +++ b/src/java/cyanogenmod/profiles/ConnectionSettings.java @@ -31,6 +31,7 @@ import android.telephony.TelephonyManager; import com.android.internal.telephony.RILConstants; +import cyanogenmod.os.Build; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -390,17 +391,47 @@ public int describeContents() { /** @hide */ @Override public void writeToParcel(Parcel dest, int flags) { + // Write parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + dest.writeInt(Build.PARCELABLE_VERSION); + + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + int sizePosition = dest.dataPosition(); + dest.writeInt(0); + int startPosition = dest.dataPosition(); + + // === BOYSENBERRY === dest.writeInt(mConnectionId); dest.writeInt(mOverride ? 1 : 0); dest.writeInt(mValue); dest.writeInt(mDirty ? 1 : 0); + + // Go back and write size + int parcelableSize = dest.dataPosition() - startPosition; + dest.setDataPosition(sizePosition); + dest.writeInt(parcelableSize); + dest.setDataPosition(startPosition + parcelableSize); } /** @hide */ public void readFromParcel(Parcel in) { - mConnectionId = in.readInt(); - mOverride = in.readInt() != 0; - mValue = in.readInt(); - mDirty = in.readInt() != 0; + // Read parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + int parcelableVersion = in.readInt(); + int parcelableSize = in.readInt(); + int startPosition = in.dataPosition(); + + // Pattern here is that all new members should be added to the end of + // the writeToParcel method. Then we step through each version, until the latest + // API release to help unravel this parcel + if (parcelableVersion >= Build.CM_VERSION_CODES.BOYSENBERRY) { + mConnectionId = in.readInt(); + mOverride = in.readInt() != 0; + mValue = in.readInt(); + mDirty = in.readInt() != 0; + } + + in.setDataPosition(startPosition + parcelableSize); } } diff --git a/src/java/cyanogenmod/profiles/RingModeSettings.java b/src/java/cyanogenmod/profiles/RingModeSettings.java index d7f6c03a..befff5d5 100644 --- a/src/java/cyanogenmod/profiles/RingModeSettings.java +++ b/src/java/cyanogenmod/profiles/RingModeSettings.java @@ -21,6 +21,7 @@ import android.os.Parcel; import android.os.Parcelable; +import cyanogenmod.os.Build; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -177,15 +178,45 @@ public int describeContents() { /** @hide */ @Override public void writeToParcel(Parcel dest, int flags) { + // Write parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + dest.writeInt(Build.PARCELABLE_VERSION); + + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + int sizePosition = dest.dataPosition(); + dest.writeInt(0); + int startPosition = dest.dataPosition(); + + // === BOYSENBERRY === dest.writeInt(mOverride ? 1 : 0); dest.writeString(mValue); dest.writeInt(mDirty ? 1 : 0); + + // Go back and write size + int parcelableSize = dest.dataPosition() - startPosition; + dest.setDataPosition(sizePosition); + dest.writeInt(parcelableSize); + dest.setDataPosition(startPosition + parcelableSize); } /** @hide */ public void readFromParcel(Parcel in) { - mOverride = in.readInt() != 0; - mValue = in.readString(); - mDirty = in.readInt() != 0; + // Read parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + int parcelableVersion = in.readInt(); + int parcelableSize = in.readInt(); + int startPosition = in.dataPosition(); + + // Pattern here is that all new members should be added to the end of + // the writeToParcel method. Then we step through each version, until the latest + // API release to help unravel this parcel + if (parcelableVersion >= Build.CM_VERSION_CODES.BOYSENBERRY) { + mOverride = in.readInt() != 0; + mValue = in.readString(); + mDirty = in.readInt() != 0; + } + + in.setDataPosition(startPosition + parcelableSize); } } diff --git a/src/java/cyanogenmod/profiles/StreamSettings.java b/src/java/cyanogenmod/profiles/StreamSettings.java index 98983343..2d8b845f 100644 --- a/src/java/cyanogenmod/profiles/StreamSettings.java +++ b/src/java/cyanogenmod/profiles/StreamSettings.java @@ -16,6 +16,7 @@ package cyanogenmod.profiles; +import cyanogenmod.os.Build; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -176,17 +177,47 @@ public int describeContents() { /** @hide */ @Override public void writeToParcel(Parcel dest, int flags) { + // Write parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + dest.writeInt(Build.PARCELABLE_VERSION); + + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + int sizePosition = dest.dataPosition(); + dest.writeInt(0); + int startPosition = dest.dataPosition(); + + // === BOYSENBERRY === dest.writeInt(mStreamId); dest.writeInt(mOverride ? 1 : 0); dest.writeInt(mValue); dest.writeInt(mDirty ? 1 : 0); + + // Go back and write size + int parcelableSize = dest.dataPosition() - startPosition; + dest.setDataPosition(sizePosition); + dest.writeInt(parcelableSize); + dest.setDataPosition(startPosition + parcelableSize); } /** @hide */ public void readFromParcel(Parcel in) { - mStreamId = in.readInt(); - mOverride = in.readInt() != 0; - mValue = in.readInt(); - mDirty = in.readInt() != 0; + // Read parcelable version, make sure to define explicit changes + // within {@link Build.PARCELABLE_VERSION); + int parcelableVersion = in.readInt(); + int parcelableSize = in.readInt(); + int startPosition = in.dataPosition(); + + // Pattern here is that all new members should be added to the end of + // the writeToParcel method. Then we step through each version, until the latest + // API release to help unravel this parcel + if (parcelableVersion >= Build.CM_VERSION_CODES.BOYSENBERRY) { + mStreamId = in.readInt(); + mOverride = in.readInt() != 0; + mValue = in.readInt(); + mDirty = in.readInt() != 0; + } + + in.setDataPosition(startPosition + parcelableSize); } }