From eafcdbd2298caba7ae7c6c4d10f0e2e445245216 Mon Sep 17 00:00:00 2001 From: Adnan Begovic Date: Tue, 29 Mar 2016 11:41:22 -0700 Subject: [PATCH] cmsdk: Create Concierge parcel handler concept. Simply, 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. 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(); Change-Id: I0096851e08ce25908e19e39e6bc4af344e85725e --- src/java/cyanogenmod/app/CustomTile.java | 90 ++++------- .../cyanogenmod/app/LiveLockScreenInfo.java | 31 ++-- src/java/cyanogenmod/app/Profile.java | 63 +++----- src/java/cyanogenmod/app/ProfileGroup.java | 40 ++--- .../app/StatusBarPanelCustomTile.java | 33 ++-- .../app/suggest/ApplicationSuggestion.java | 32 ++-- .../cyanogenmod/hardware/DisplayMode.java | 32 ++-- src/java/cyanogenmod/os/Build.java | 11 -- src/java/cyanogenmod/os/Concierge.java | 150 ++++++++++++++++++ .../profiles/AirplaneModeSettings.java | 32 ++-- .../profiles/BrightnessSettings.java | 32 ++-- .../profiles/ConnectionSettings.java | 32 ++-- .../cyanogenmod/profiles/LockSettings.java | 34 ++-- .../profiles/RingModeSettings.java | 32 ++-- .../cyanogenmod/profiles/StreamSettings.java | 41 ++--- .../themes/ThemeChangeRequest.java | 33 ++-- src/java/cyanogenmod/weather/RequestInfo.java | 27 ++-- src/java/cyanogenmod/weather/WeatherInfo.java | 51 +++--- .../cyanogenmod/weather/WeatherLocation.java | 27 ++-- .../weatherservice/ServiceRequestResult.java | 27 ++-- .../tests/versioning/unit/BuildTest.java | 7 +- 21 files changed, 428 insertions(+), 429 deletions(-) create mode 100644 src/java/cyanogenmod/os/Concierge.java diff --git a/src/java/cyanogenmod/app/CustomTile.java b/src/java/cyanogenmod/app/CustomTile.java index 26ff6b4..dee8c37 100644 --- a/src/java/cyanogenmod/app/CustomTile.java +++ b/src/java/cyanogenmod/app/CustomTile.java @@ -28,6 +28,9 @@ import android.util.Log; import android.widget.RemoteViews; import cyanogenmod.os.Build; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; + import java.util.ArrayList; /** @@ -128,11 +131,9 @@ public class CustomTile implements Parcelable { * Unflatten the CustomTile from a parcel. */ public CustomTile(Parcel parcel) { - // 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(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(parcel); + int parcelableVersion = parcelInfo.getParcelVersion(); // 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 @@ -177,7 +178,8 @@ public class CustomTile implements Parcelable { } } - parcel.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } /** @@ -267,15 +269,8 @@ public class CustomTile implements Parcelable { @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(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(out); // ==== APRICOT ===== if (onClick != null) { @@ -341,11 +336,8 @@ public class CustomTile implements Parcelable { out.writeInt(0); } - // Go back and write size - int parcelableSize = out.dataPosition() - startPosition; - out.setDataPosition(sizePosition); - out.writeInt(parcelableSize); - out.setDataPosition(startPosition + parcelableSize); + // Complete the parcel info for the concierge + parcelInfo.complete(); } /** @@ -382,11 +374,9 @@ public class CustomTile implements Parcelable { private int styleId; private ExpandedStyle(Parcel parcel) { - // 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(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(parcel); + int parcelableVersion = parcelInfo.getParcelVersion(); // 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 @@ -404,7 +394,8 @@ public class CustomTile implements Parcelable { } } - parcel.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } /** @@ -473,15 +464,8 @@ public class CustomTile implements Parcelable { @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(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(parcel); // ==== APRICOT ==== if (expandedItems != null) { @@ -500,11 +484,8 @@ public class CustomTile implements Parcelable { parcel.writeInt(0); } - // Go back and write size - int parcelableSize = parcel.dataPosition() - startPosition; - parcel.setDataPosition(sizePosition); - parcel.writeInt(parcelableSize); - parcel.setDataPosition(startPosition + parcelableSize); + // Complete the parcel info for the concierge + parcelInfo.complete(); } @Override @@ -679,11 +660,9 @@ public class CustomTile implements Parcelable { * Unflatten the ExpandedItem from a parcel. */ protected ExpandedItem(Parcel parcel) { - // 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(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(parcel); + int parcelableVersion = parcelInfo.getParcelVersion(); // 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 @@ -707,7 +686,8 @@ public class CustomTile implements Parcelable { } } - parcel.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } @Override @@ -717,15 +697,8 @@ public class CustomTile implements Parcelable { @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(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(out); // ==== APRICOT ==== if (onClickPendingIntent != null) { @@ -756,11 +729,8 @@ public class CustomTile implements Parcelable { out.writeInt(0); } - // Go back and write size - int parcelableSize = out.dataPosition() - startPosition; - out.setDataPosition(sizePosition); - out.writeInt(parcelableSize); - out.setDataPosition(startPosition + parcelableSize); + // Complete the parcel info for the concierge + parcelInfo.complete(); } @Override diff --git a/src/java/cyanogenmod/app/LiveLockScreenInfo.java b/src/java/cyanogenmod/app/LiveLockScreenInfo.java index 33afd89..5ac2220 100644 --- a/src/java/cyanogenmod/app/LiveLockScreenInfo.java +++ b/src/java/cyanogenmod/app/LiveLockScreenInfo.java @@ -22,7 +22,10 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; + import cyanogenmod.os.Build; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; /** * Data structure defining a Live lock screen. @@ -86,11 +89,9 @@ public class LiveLockScreenInfo implements Parcelable { } private LiveLockScreenInfo(Parcel source) { - // Read parcelable version, make sure to define explicit changes - // within {@link Build.PARCELABLE_VERSION); - int version = source.readInt(); - int size = source.readInt(); - int start = source.dataPosition(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(source); + int parcelableVersion = parcelInfo.getParcelVersion(); this.priority = source.readInt(); String component = source.readString(); @@ -98,7 +99,8 @@ public class LiveLockScreenInfo implements Parcelable { ? ComponentName.unflattenFromString(component) : null; - source.setDataPosition(start + size); + // Complete parcel info for the concierge + parcelInfo.complete(); } @Override @@ -108,23 +110,14 @@ public class LiveLockScreenInfo implements Parcelable { @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); - int sizePos = dest.dataPosition(); - // Inject a placeholder that will store the parcel size from this point on - // (not including the size itself). - dest.writeInt(0); - int dataStartPos = dest.dataPosition(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); dest.writeInt(priority); dest.writeString(component != null ? component.flattenToString() : ""); - // Go back and write size - int size = dest.dataPosition() - dataStartPos; - dest.setDataPosition(sizePos); - dest.writeInt(size); - dest.setDataPosition(dataStartPos + size); + // Complete the parcel info for the concierge + parcelInfo.complete(); } @Override diff --git a/src/java/cyanogenmod/app/Profile.java b/src/java/cyanogenmod/app/Profile.java index 3977b38..9a4666d 100755 --- a/src/java/cyanogenmod/app/Profile.java +++ b/src/java/cyanogenmod/app/Profile.java @@ -35,13 +35,15 @@ import cyanogenmod.profiles.LockSettings; import cyanogenmod.profiles.RingModeSettings; import cyanogenmod.profiles.StreamSettings; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -227,11 +229,9 @@ public final class Profile implements Parcelable, Comparable { } private ProfileTrigger(Parcel in) { - // 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(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(in); + int parcelableVersion = parcelInfo.getParcelVersion(); // 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 @@ -243,31 +243,22 @@ public final class Profile implements Parcelable, Comparable { mName = in.readString(); } - in.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } @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(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); 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); + // Complete the parcel info for the concierge + parcelInfo.complete(); } @Override @@ -547,15 +538,8 @@ public final class Profile implements Parcelable, Comparable { /** @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(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // === BOYSENBERRY === if (!TextUtils.isEmpty(mName)) { @@ -649,21 +633,15 @@ public final class Profile implements Parcelable, Comparable { dest.writeInt(0); } - - // Go back and write size - int parcelableSize = dest.dataPosition() - startPosition; - dest.setDataPosition(sizePosition); - dest.writeInt(parcelableSize); - dest.setDataPosition(startPosition + parcelableSize); + // Complete the parcel info for the concierge + parcelInfo.complete(); } /** @hide */ public void readFromParcel(Parcel in) { - // 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(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(in); + int parcelableVersion = parcelInfo.getParcelVersion(); // 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 @@ -735,7 +713,8 @@ public final class Profile implements Parcelable, Comparable { } } - in.setDataPosition(startPosition + parcelableSize); + // Complete the parcel info for the concierge + parcelInfo.complete(); } /** diff --git a/src/java/cyanogenmod/app/ProfileGroup.java b/src/java/cyanogenmod/app/ProfileGroup.java index 5109e9d..56ec507 100644 --- a/src/java/cyanogenmod/app/ProfileGroup.java +++ b/src/java/cyanogenmod/app/ProfileGroup.java @@ -18,9 +18,6 @@ package cyanogenmod.app; import android.app.Notification; import android.app.NotificationGroup; -import cyanogenmod.os.Build; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; import android.content.Context; import android.database.Cursor; @@ -32,9 +29,17 @@ import android.os.ParcelUuid; import android.text.TextUtils; import android.util.Log; +import cyanogenmod.os.Build; + +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; + import java.io.IOException; import java.util.UUID; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + /** * @hide * TODO: This isn't ready for public use @@ -264,15 +269,8 @@ public final class ProfileGroup implements Parcelable { /** @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(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // === BOYSENBERRY === dest.writeString(mName); @@ -286,20 +284,15 @@ public final class ProfileGroup implements Parcelable { 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); + // Complete the parcel info for the concierge + parcelInfo.complete(); } /** @hide */ public void readFromParcel(Parcel in) { - // 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(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(in); + int parcelableVersion = parcelInfo.getParcelVersion(); // 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 @@ -318,7 +311,8 @@ public final class ProfileGroup implements Parcelable { mLightsMode = Mode.valueOf(Mode.class, in.readString()); } - in.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } public enum Mode { diff --git a/src/java/cyanogenmod/app/StatusBarPanelCustomTile.java b/src/java/cyanogenmod/app/StatusBarPanelCustomTile.java index d467aec..7710e5a 100644 --- a/src/java/cyanogenmod/app/StatusBarPanelCustomTile.java +++ b/src/java/cyanogenmod/app/StatusBarPanelCustomTile.java @@ -19,8 +19,12 @@ package cyanogenmod.app; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; + import cyanogenmod.os.Build; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; + /** * Class encapsulating a Custom Tile. Sent by the StatusBarManagerService to clients including * the status bar panel and any {@link cyanogenmod.app.CustomTileListenerService} clients. @@ -67,11 +71,9 @@ public class StatusBarPanelCustomTile implements Parcelable { public StatusBarPanelCustomTile(Parcel in) { - // 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(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(in); + int parcelableVersion = parcelInfo.getParcelVersion(); // tmp variables for final String tmpResPkg = null; @@ -122,7 +124,8 @@ public class StatusBarPanelCustomTile implements Parcelable { this.postTime = tmpPostTime; this.key = key(); - in.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } private String key() { @@ -157,15 +160,8 @@ public class StatusBarPanelCustomTile implements Parcelable { @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(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(out); // ==== APRICOT === out.writeString(this.pkg); @@ -186,11 +182,8 @@ public class StatusBarPanelCustomTile implements Parcelable { // ==== 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); + // Complete the parcel info for the concierge + parcelInfo.complete(); } @Override diff --git a/src/java/cyanogenmod/app/suggest/ApplicationSuggestion.java b/src/java/cyanogenmod/app/suggest/ApplicationSuggestion.java index c10afe3..17e40b9 100644 --- a/src/java/cyanogenmod/app/suggest/ApplicationSuggestion.java +++ b/src/java/cyanogenmod/app/suggest/ApplicationSuggestion.java @@ -20,7 +20,10 @@ import android.annotation.NonNull; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; + import cyanogenmod.os.Build; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; /** * @hide @@ -55,11 +58,9 @@ public class ApplicationSuggestion implements Parcelable { } private ApplicationSuggestion(Parcel in) { - // 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(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(in); + int parcelableVersion = parcelInfo.getParcelVersion(); if (parcelableVersion >= Build.CM_VERSION_CODES.APRICOT) { mName = in.readString(); @@ -68,7 +69,8 @@ public class ApplicationSuggestion implements Parcelable { mThumbnailUri = in.readParcelable(Uri.class.getClassLoader()); } - in.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } @Override @@ -78,26 +80,16 @@ public class ApplicationSuggestion implements Parcelable { @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(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(out); out.writeString(mName); out.writeString(mPackage); out.writeParcelable(mDownloadUri, flags); out.writeParcelable(mThumbnailUri, flags); - // Go back and write size - int parcelableSize = out.dataPosition() - startPosition; - out.setDataPosition(sizePosition); - out.writeInt(parcelableSize); - out.setDataPosition(startPosition + parcelableSize); + // Complete the parcel info for the concierge + parcelInfo.complete(); } public String getName() { diff --git a/src/java/cyanogenmod/hardware/DisplayMode.java b/src/java/cyanogenmod/hardware/DisplayMode.java index 908d428..77172b8 100644 --- a/src/java/cyanogenmod/hardware/DisplayMode.java +++ b/src/java/cyanogenmod/hardware/DisplayMode.java @@ -20,6 +20,8 @@ import android.os.Parcel; import android.os.Parcelable; import cyanogenmod.os.Build; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; /** * Display Modes API @@ -45,11 +47,9 @@ public class DisplayMode implements Parcelable { } private DisplayMode(Parcel parcel) { - // 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(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(parcel); + int parcelableVersion = parcelInfo.getParcelVersion(); // temp vars int tmpId = -1; @@ -65,7 +65,9 @@ public class DisplayMode implements Parcelable { // set temps this.id = tmpId; this.name = tmpName; - parcel.setDataPosition(startPosition + parcelableSize); + + // Complete parcel info for the concierge + parcelInfo.complete(); } @Override @@ -75,15 +77,8 @@ public class DisplayMode implements Parcelable { @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(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(out); // ==== BOYSENBERRY ===== out.writeInt(id); @@ -94,11 +89,8 @@ public class DisplayMode implements Parcelable { out.writeInt(0); } - // Go back and write size - int parcelableSize = out.dataPosition() - startPosition; - out.setDataPosition(sizePosition); - out.writeInt(parcelableSize); - out.setDataPosition(startPosition + parcelableSize); + // Complete the parcel info for the concierge + parcelInfo.complete(); } /** @hide */ diff --git a/src/java/cyanogenmod/os/Build.java b/src/java/cyanogenmod/os/Build.java index 89ac537..ce7b8fb 100644 --- a/src/java/cyanogenmod/os/Build.java +++ b/src/java/cyanogenmod/os/Build.java @@ -27,17 +27,6 @@ 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} - * @hide - */ - public static final int PARCELABLE_VERSION = CM_VERSION_CODES.ELDERBERRY; - /** A build ID utilized to distinguish cyanogenmod versions */ public static final String CYANOGENMOD_VERSION = "ro.cm.version"; diff --git a/src/java/cyanogenmod/os/Concierge.java b/src/java/cyanogenmod/os/Concierge.java new file mode 100644 index 0000000..5d86e82 --- /dev/null +++ b/src/java/cyanogenmod/os/Concierge.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cyanogenmod.os; + +import android.os.Parcel; + +import cyanogenmod.os.Build.CM_VERSION_CODES; + +/** + * Simply, 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. + * + *

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();
+ * 
+ * + * {@hide} // Unhide? + */ +public final class Concierge { + + /** Not instantiable */ + private Concierge() { + // Don't instantiate + } + + /** + * 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} + * @hide + */ + public static final int PARCELABLE_VERSION = CM_VERSION_CODES.ELDERBERRY; + + /** + * Tell the concierge to receive our parcel, so we can get information from it. + * + * MUST CALL {@link ParcelInfo#complete()} AFTER UNMARSHALLING. + * + * @param parcel Incoming parcel to be unmarshalled + * @return {@link ParcelInfo} containing parcel information, specifically the version. + */ + public static ParcelInfo receiveParcel(Parcel parcel) { + return new ParcelInfo(parcel); + } + + /** + * Prepare a parcel for the Concierge. + * + * MUST CALL {@link ParcelInfo#complete()} AFTER MARSHALLING. + * + * @param parcel Outgoing parcel to be marshalled + * @return {@link ParcelInfo} containing parcel information, specifically the version. + */ + public static ParcelInfo prepareParcel(Parcel parcel) { + return new ParcelInfo(parcel, PARCELABLE_VERSION); + } + + public final static class ParcelInfo { + private Parcel mParcel; + private int mParcelableVersion; + private int mParcelableSize; + private int mStartPosition; + private int mSizePosition; + private boolean mCreation = false; + + ParcelInfo(Parcel parcel) { + mCreation = false; + mParcel = parcel; + mParcelableVersion = parcel.readInt(); + mParcelableSize = parcel.readInt(); + mStartPosition = parcel.dataPosition(); + } + + ParcelInfo(Parcel parcel, int parcelableVersion) { + mCreation = true; + mParcel = parcel; + mParcelableVersion = parcelableVersion; + + // 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(); + } + + /** + * Get the parcel version from the {@link Parcel} received by the Concierge. + * @return {@link #PARCELABLE_VERSION} of the {@link Parcel} + */ + public int getParcelVersion() { + return mParcelableVersion; + } + + /** + * Complete the {@link ParcelInfo} for the Concierge. + */ + public void complete() { + if (mCreation) { + // Go back and write size + mParcelableSize = mParcel.dataPosition() - mStartPosition; + mParcel.setDataPosition(mSizePosition); + mParcel.writeInt(mParcelableSize); + mParcel.setDataPosition(mStartPosition + mParcelableSize); + } else { + mParcel.setDataPosition(mStartPosition + mParcelableSize); + } + } + } +} diff --git a/src/java/cyanogenmod/profiles/AirplaneModeSettings.java b/src/java/cyanogenmod/profiles/AirplaneModeSettings.java index f79bf84..a9b828f 100644 --- a/src/java/cyanogenmod/profiles/AirplaneModeSettings.java +++ b/src/java/cyanogenmod/profiles/AirplaneModeSettings.java @@ -23,6 +23,9 @@ import android.os.Parcel; import android.os.Parcelable; import cyanogenmod.os.Build; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -188,35 +191,23 @@ public final class AirplaneModeSettings implements Parcelable { /** @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(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // === 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); + // Complete the parcel info for the concierge + parcelInfo.complete(); } /** @hide */ public void readFromParcel(Parcel in) { - // 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(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(in); + int parcelableVersion = parcelInfo.getParcelVersion(); // 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 @@ -227,6 +218,7 @@ public final class AirplaneModeSettings implements Parcelable { mDirty = in.readInt() != 0; } - in.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } } diff --git a/src/java/cyanogenmod/profiles/BrightnessSettings.java b/src/java/cyanogenmod/profiles/BrightnessSettings.java index eb74491..0786a72 100644 --- a/src/java/cyanogenmod/profiles/BrightnessSettings.java +++ b/src/java/cyanogenmod/profiles/BrightnessSettings.java @@ -22,6 +22,9 @@ import android.os.Parcel; import android.os.Parcelable; import cyanogenmod.os.Build; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -186,35 +189,23 @@ public final class BrightnessSettings implements Parcelable { /** @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(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // === 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); + // Complete the parcel info for the concierge + parcelInfo.complete(); } /** @hide */ public void readFromParcel(Parcel in) { - // 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(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(in); + int parcelableVersion = parcelInfo.getParcelVersion(); // 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 @@ -225,6 +216,7 @@ public final class BrightnessSettings implements Parcelable { mDirty = in.readInt() != 0; } - in.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } } diff --git a/src/java/cyanogenmod/profiles/ConnectionSettings.java b/src/java/cyanogenmod/profiles/ConnectionSettings.java index 0370062..19954dd 100644 --- a/src/java/cyanogenmod/profiles/ConnectionSettings.java +++ b/src/java/cyanogenmod/profiles/ConnectionSettings.java @@ -32,6 +32,9 @@ import android.telephony.TelephonyManager; import com.android.internal.telephony.RILConstants; import cyanogenmod.os.Build; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -426,15 +429,8 @@ public final class ConnectionSettings implements Parcelable { /** @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(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // === BOYSENBERRY === dest.writeInt(mConnectionId); @@ -447,20 +443,15 @@ public final class ConnectionSettings implements Parcelable { dest.writeInt(mSubId); } - // Go back and write size - int parcelableSize = dest.dataPosition() - startPosition; - dest.setDataPosition(sizePosition); - dest.writeInt(parcelableSize); - dest.setDataPosition(startPosition + parcelableSize); + // Complete the parcel info for the concierge + parcelInfo.complete(); } /** @hide */ public void readFromParcel(Parcel in) { - // 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(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(in); + int parcelableVersion = parcelInfo.getParcelVersion(); // 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 @@ -478,6 +469,7 @@ public final class ConnectionSettings implements Parcelable { } } - in.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } } diff --git a/src/java/cyanogenmod/profiles/LockSettings.java b/src/java/cyanogenmod/profiles/LockSettings.java index 9c86c42..2be3725 100644 --- a/src/java/cyanogenmod/profiles/LockSettings.java +++ b/src/java/cyanogenmod/profiles/LockSettings.java @@ -21,14 +21,15 @@ import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; -import android.os.ServiceManager; import android.util.Log; -import android.view.WindowManagerPolicy; /* import android.view.WindowManagerPolicyControl; */ import com.android.internal.policy.IKeyguardService; /* import com.android.internal.policy.PolicyManager; */ + import cyanogenmod.app.Profile; import cyanogenmod.os.Build; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; /** * The {@link LockSettings} class allows for overriding and setting the @@ -147,34 +148,22 @@ public final class LockSettings implements Parcelable { /** @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(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // === BOYSENBERRY === 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); + // Complete the parcel info for the concierge + parcelInfo.complete(); } /** @hide */ public void readFromParcel(Parcel in) { - // 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(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(in); + int parcelableVersion = parcelInfo.getParcelVersion(); // 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 @@ -184,6 +173,7 @@ public final class LockSettings implements Parcelable { mDirty = in.readInt() != 0; } - in.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } } diff --git a/src/java/cyanogenmod/profiles/RingModeSettings.java b/src/java/cyanogenmod/profiles/RingModeSettings.java index befff5d..bab74ac 100644 --- a/src/java/cyanogenmod/profiles/RingModeSettings.java +++ b/src/java/cyanogenmod/profiles/RingModeSettings.java @@ -22,6 +22,9 @@ import android.os.Parcel; import android.os.Parcelable; import cyanogenmod.os.Build; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -178,35 +181,23 @@ public final class RingModeSettings implements Parcelable { /** @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(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // === 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); + // Complete the parcel info for the concierge + parcelInfo.complete(); } /** @hide */ public void readFromParcel(Parcel in) { - // 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(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(in); + int parcelableVersion = parcelInfo.getParcelVersion(); // 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 @@ -217,6 +208,7 @@ public final class RingModeSettings implements Parcelable { mDirty = in.readInt() != 0; } - in.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } } diff --git a/src/java/cyanogenmod/profiles/StreamSettings.java b/src/java/cyanogenmod/profiles/StreamSettings.java index 2d8b845..9ce9415 100644 --- a/src/java/cyanogenmod/profiles/StreamSettings.java +++ b/src/java/cyanogenmod/profiles/StreamSettings.java @@ -16,16 +16,20 @@ package cyanogenmod.profiles; -import cyanogenmod.os.Build; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - import android.content.Context; import android.os.Parcel; import android.os.Parcelable; + +import cyanogenmod.os.Build; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; + import java.io.IOException; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + /** * The {@link StreamSettings} class allows for creating various {@link android.media.AudioManager} * overrides on the device depending on their capabilities. @@ -177,15 +181,8 @@ public final class StreamSettings implements Parcelable{ /** @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(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // === BOYSENBERRY === dest.writeInt(mStreamId); @@ -193,20 +190,15 @@ public final class StreamSettings implements Parcelable{ 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); + // Complete the parcel info for the concierge + parcelInfo.complete(); } /** @hide */ public void readFromParcel(Parcel in) { - // 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(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(in); + int parcelableVersion = parcelInfo.getParcelVersion(); // 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 @@ -218,6 +210,7 @@ public final class StreamSettings implements Parcelable{ mDirty = in.readInt() != 0; } - in.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } } diff --git a/src/java/cyanogenmod/themes/ThemeChangeRequest.java b/src/java/cyanogenmod/themes/ThemeChangeRequest.java index 5eb497e..f8eeeb5 100644 --- a/src/java/cyanogenmod/themes/ThemeChangeRequest.java +++ b/src/java/cyanogenmod/themes/ThemeChangeRequest.java @@ -19,7 +19,9 @@ import android.content.pm.ThemeUtils; import android.content.res.ThemeConfig; import android.os.Parcel; import android.os.Parcelable; -import cyanogenmod.os.Build; + +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; import java.util.Collections; import java.util.HashMap; @@ -124,11 +126,9 @@ public final class ThemeChangeRequest implements Parcelable { } private ThemeChangeRequest(Parcel source) { - // Read parcelable version, make sure to define explicit changes - // within {@link Build.PARCELABLE_VERSION); - int version = source.readInt(); - int size = source.readInt(); - int start = source.dataPosition(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(source); + int parcelableVersion = parcelInfo.getParcelVersion(); int numComponents = source.readInt(); for (int i = 0; i < numComponents; i++) { @@ -141,7 +141,9 @@ public final class ThemeChangeRequest implements Parcelable { } mRequestType = RequestType.values()[source.readInt()]; mWallpaperId = source.readLong(); - source.setDataPosition(start + size); + + // Complete parcel info for the concierge + parcelInfo.complete(); } @Override @@ -151,14 +153,8 @@ public final class ThemeChangeRequest implements Parcelable { @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); - int sizePos = dest.dataPosition(); - // Inject a placeholder that will store the parcel size from this point on - // (not including the size itself). - dest.writeInt(0); - int dataStartPos = dest.dataPosition(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); dest.writeInt(mThemeComponents.size()); for (String component : mThemeComponents.keySet()) { @@ -173,11 +169,8 @@ public final class ThemeChangeRequest implements Parcelable { dest.writeInt(mRequestType.ordinal()); dest.writeLong(mWallpaperId); - // Go back and write size - int size = dest.dataPosition() - dataStartPos; - dest.setDataPosition(sizePos); - dest.writeInt(size); - dest.setDataPosition(dataStartPos + size); + // Complete the parcel info for the concierge + parcelInfo.complete(); } public static final Parcelable.Creator CREATOR = diff --git a/src/java/cyanogenmod/weather/RequestInfo.java b/src/java/cyanogenmod/weather/RequestInfo.java index e99af98..353b5fd 100644 --- a/src/java/cyanogenmod/weather/RequestInfo.java +++ b/src/java/cyanogenmod/weather/RequestInfo.java @@ -19,7 +19,10 @@ package cyanogenmod.weather; import android.location.Location; import android.os.Parcel; import android.os.Parcelable; + import cyanogenmod.os.Build; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; import cyanogenmod.providers.WeatherContract; /** @@ -164,9 +167,10 @@ public final class RequestInfo implements Parcelable { } private RequestInfo(Parcel parcel) { - int parcelableVersion = parcel.readInt(); - int parcelableSize = parcel.readInt(); - int startPosition = parcel.dataPosition(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(parcel); + int parcelableVersion = parcelInfo.getParcelVersion(); + if (parcelableVersion >= Build.CM_VERSION_CODES.ELDERBERRY) { mKey = parcel.readInt(); mRequestType = parcel.readInt(); @@ -186,7 +190,9 @@ public final class RequestInfo implements Parcelable { mIsQueryOnly = (parcel.readInt() == 1); mListener = IRequestInfoListener.Stub.asInterface(parcel.readStrongBinder()); } - parcel.setDataPosition(startPosition + parcelableSize); + + // Complete parcel info for the concierge + parcelInfo.complete(); } @@ -274,11 +280,8 @@ public final class RequestInfo implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(Build.PARCELABLE_VERSION); - - int sizePosition = dest.dataPosition(); - dest.writeInt(0); - int startPosition = dest.dataPosition(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // ==== ELDERBERRY ===== dest.writeInt(mKey); @@ -299,10 +302,8 @@ public final class RequestInfo implements Parcelable { dest.writeInt(mIsQueryOnly == true ? 1 : 0); dest.writeStrongBinder(mListener.asBinder()); - int parcelableSize = dest.dataPosition() - startPosition; - dest.setDataPosition(sizePosition); - dest.writeInt(parcelableSize); - dest.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } @Override diff --git a/src/java/cyanogenmod/weather/WeatherInfo.java b/src/java/cyanogenmod/weather/WeatherInfo.java index 3fd2eac..7d8686e 100755 --- a/src/java/cyanogenmod/weather/WeatherInfo.java +++ b/src/java/cyanogenmod/weather/WeatherInfo.java @@ -19,7 +19,10 @@ package cyanogenmod.weather; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; + import cyanogenmod.os.Build; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; import cyanogenmod.providers.WeatherContract; import cyanogenmod.weatherservice.ServiceRequest; import cyanogenmod.weatherservice.ServiceRequestResult; @@ -261,9 +264,10 @@ public final class WeatherInfo implements Parcelable { } private WeatherInfo(Parcel parcel) { - int parcelableVersion = parcel.readInt(); - int parcelableSize = parcel.readInt(); - int startPosition = parcel.dataPosition(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(parcel); + int parcelableVersion = parcelInfo.getParcelVersion(); + if (parcelableVersion >= Build.CM_VERSION_CODES.ELDERBERRY) { mKey = parcel.readInt(); mCityId = parcel.readString(); @@ -283,7 +287,9 @@ public final class WeatherInfo implements Parcelable { forecastListSize--; } } - parcel.setDataPosition(startPosition + parcelableSize); + + // Complete parcel info for the concierge + parcelInfo.complete(); } @Override @@ -293,11 +299,8 @@ public final class WeatherInfo implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(Build.PARCELABLE_VERSION); - - int sizePosition = dest.dataPosition(); - dest.writeInt(0); - int startPosition = dest.dataPosition(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // ==== ELDERBERRY ===== dest.writeInt(mKey); @@ -316,10 +319,8 @@ public final class WeatherInfo implements Parcelable { dayForecast.writeToParcel(dest, 0); } - int parcelableSize = dest.dataPosition() - startPosition; - dest.setDataPosition(sizePosition); - dest.writeInt(parcelableSize); - dest.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } public static final Parcelable.Creator CREATOR = @@ -414,11 +415,8 @@ public final class WeatherInfo implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(Build.PARCELABLE_VERSION); - - int sizePosition = dest.dataPosition(); - dest.writeInt(0); - int startPosition = dest.dataPosition(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // ==== ELDERBERRY ===== dest.writeInt(mKey); @@ -426,10 +424,8 @@ public final class WeatherInfo implements Parcelable { dest.writeFloat(mHigh); dest.writeInt(mConditionCode); - int parcelableSize = dest.dataPosition() - startPosition; - dest.setDataPosition(sizePosition); - dest.writeInt(parcelableSize); - dest.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } public static final Parcelable.Creator CREATOR = @@ -446,16 +442,19 @@ public final class WeatherInfo implements Parcelable { }; private DayForecast(Parcel parcel) { - int parcelableVersion = parcel.readInt(); - int parcelableSize = parcel.readInt(); - int startPosition = parcel.dataPosition(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(parcel); + int parcelableVersion = parcelInfo.getParcelVersion(); + if (parcelableVersion >= Build.CM_VERSION_CODES.ELDERBERRY) { mKey = parcel.readInt(); mLow = parcel.readFloat(); mHigh = parcel.readFloat(); mConditionCode = parcel.readInt(); } - parcel.setDataPosition(startPosition + parcelableSize); + + // Complete parcel info for the concierge + parcelInfo.complete(); } @Override diff --git a/src/java/cyanogenmod/weather/WeatherLocation.java b/src/java/cyanogenmod/weather/WeatherLocation.java index b7827e9..3afcd8e 100644 --- a/src/java/cyanogenmod/weather/WeatherLocation.java +++ b/src/java/cyanogenmod/weather/WeatherLocation.java @@ -18,7 +18,10 @@ package cyanogenmod.weather; import android.os.Parcel; import android.os.Parcelable; + import cyanogenmod.os.Build; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; /** * A class representing a geographical location that a weather service provider can use to @@ -92,9 +95,10 @@ public final class WeatherLocation implements Parcelable{ } private WeatherLocation(Parcel in) { - int parcelableVersion = in.readInt(); - int parcelableSize = in.readInt(); - int startPosition = in.dataPosition(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(in); + int parcelableVersion = parcelInfo.getParcelVersion(); + if (parcelableVersion >= Build.CM_VERSION_CODES.ELDERBERRY) { mKey = in.readInt(); mCityId = in.readString(); @@ -103,7 +107,9 @@ public final class WeatherLocation implements Parcelable{ mCountryId = in.readString(); mCountry = in.readString(); } - in.setDataPosition(startPosition + parcelableSize); + + // Complete parcel info for the concierge + parcelInfo.complete(); } public static final Creator CREATOR = new Creator() { @@ -125,11 +131,8 @@ public final class WeatherLocation implements Parcelable{ @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(Build.PARCELABLE_VERSION); - - int sizePosition = dest.dataPosition(); - dest.writeInt(0); - int startPosition = dest.dataPosition(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // ==== ELDERBERRY ===== dest.writeInt(mKey); @@ -139,10 +142,8 @@ public final class WeatherLocation implements Parcelable{ dest.writeString(mCountryId); dest.writeString(mCountry); - int parcelableSize = dest.dataPosition() - startPosition; - dest.setDataPosition(sizePosition); - dest.writeInt(parcelableSize); - dest.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } @Override diff --git a/src/java/cyanogenmod/weatherservice/ServiceRequestResult.java b/src/java/cyanogenmod/weatherservice/ServiceRequestResult.java index 2e962a9..07f4cd9 100644 --- a/src/java/cyanogenmod/weatherservice/ServiceRequestResult.java +++ b/src/java/cyanogenmod/weatherservice/ServiceRequestResult.java @@ -19,7 +19,10 @@ package cyanogenmod.weatherservice; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; + import cyanogenmod.os.Build; +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; import cyanogenmod.weather.WeatherLocation; import cyanogenmod.weather.WeatherInfo; @@ -37,9 +40,10 @@ public final class ServiceRequestResult implements Parcelable { private ServiceRequestResult() {} private ServiceRequestResult(Parcel in) { - int parcelableVersion = in.readInt(); - int parcelableSize = in.readInt(); - int startPosition = in.dataPosition(); + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(in); + int parcelableVersion = parcelInfo.getParcelVersion(); + if (parcelableVersion >= Build.CM_VERSION_CODES.ELDERBERRY) { mKey = in.readInt(); int hasWeatherInfo = in.readInt(); @@ -56,7 +60,9 @@ public final class ServiceRequestResult implements Parcelable { } } } - in.setDataPosition(startPosition + parcelableSize); + + // Complete parcel info for the concierge + parcelInfo.complete(); } public static final Creator CREATOR @@ -79,11 +85,8 @@ public final class ServiceRequestResult implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(Build.PARCELABLE_VERSION); - - int sizePosition = dest.dataPosition(); - dest.writeInt(0); - int startPosition = dest.dataPosition(); + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // ==== ELDERBERRY ===== dest.writeInt(mKey); @@ -103,10 +106,8 @@ public final class ServiceRequestResult implements Parcelable { dest.writeInt(0); } - int parcelableSize = dest.dataPosition() - startPosition; - dest.setDataPosition(sizePosition); - dest.writeInt(parcelableSize); - dest.setDataPosition(startPosition + parcelableSize); + // Complete parcel info for the concierge + parcelInfo.complete(); } public static class Builder { diff --git a/tests/src/org/cyanogenmod/tests/versioning/unit/BuildTest.java b/tests/src/org/cyanogenmod/tests/versioning/unit/BuildTest.java index 3e0be19..1922e95 100644 --- a/tests/src/org/cyanogenmod/tests/versioning/unit/BuildTest.java +++ b/tests/src/org/cyanogenmod/tests/versioning/unit/BuildTest.java @@ -20,6 +20,7 @@ import android.test.suitebuilder.annotation.SmallTest; import cyanogenmod.os.Build; import android.test.AndroidTestCase; +import cyanogenmod.os.Concierge; /** * Created by adnan on 7/14/15. @@ -38,20 +39,20 @@ public class BuildTest extends AndroidTestCase { @SmallTest public void testSdkApiLevelCurrent() { - assertEquals(Build.PARCELABLE_VERSION, Build.CM_VERSION.SDK_INT); + assertEquals(Concierge.PARCELABLE_VERSION, Build.CM_VERSION.SDK_INT); } @SmallTest public void testSdkApiLevelCanMatch() { String apiName = Build.getNameForSDKInt(Build.CM_VERSION.SDK_INT); assertNotNull(apiName); - assertEquals(Build.getNameForSDKInt(Build.PARCELABLE_VERSION), apiName); + assertEquals(Build.getNameForSDKInt(Concierge.PARCELABLE_VERSION), apiName); } @SmallTest public void testSdkApiLevelSkippedIfGreaterThanAllowed() { int i = 0; - if (Build.CM_VERSION.SDK_INT > Build.PARCELABLE_VERSION + 1) { + if (Build.CM_VERSION.SDK_INT > Concierge.PARCELABLE_VERSION + 1) { i++; } assertEquals(0, i);