Fix a few corner-cases with parcelling SparseArrays and Maps

Also added a test for some similar parcelling corner cases

Test: . frameworks/base/tests/Codegen/runTest.sh
Fixes: 141877655
Change-Id: Iad5c3b0a8489206754f6ebe6acb8b56ba9ca174a
diff --git a/tests/Codegen/runTest.sh b/tests/Codegen/runTest.sh
index 614cbb7..01522735 100755
--- a/tests/Codegen/runTest.sh
+++ b/tests/Codegen/runTest.sh
@@ -13,6 +13,7 @@
     header_and_eval m -j16 codegen_cli && \
         header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/SampleDataClass.java && \
         header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java && \
+        header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java && \
         cd $ANDROID_BUILD_TOP &&
         header_and_eval mmma -j16 frameworks/base/tests/Codegen && \
         header_and_eval adb install -r -t $ANDROID_PRODUCT_OUT/testcases/CodegenTests/arm64/CodegenTests.apk && \
diff --git a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
new file mode 100644
index 0000000..2d41257
--- /dev/null
+++ b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2019 The Android Open Source 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 com.android.codegentest;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+
+import com.android.internal.util.AnnotationValidations;
+import com.android.internal.util.DataClass;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Additional test for various parcelling corner-cases.
+ */
+@DataClass(
+        genBuilder = true,
+        genAidl = false,
+        genToString = true)
+public class ParcelAllTheThingsDataClass implements Parcelable {
+
+    @NonNull String[] mStringArray = null;
+    @NonNull int[] mIntArray = null;
+    @NonNull List<String> mStringList = null;
+
+    @NonNull Map<String, SampleWithCustomBuilder> mMap = null;
+    @NonNull Map<String, String> mStringMap = null;
+
+    @NonNull SparseArray<SampleWithCustomBuilder> mSparseArray = null;
+    @NonNull SparseIntArray mSparseIntArray = null;
+
+
+
+    // Code below generated by codegen v1.0.4.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
+
+
+    @DataClass.Generated.Member
+    /* package-private */ ParcelAllTheThingsDataClass(
+            @NonNull String[] stringArray,
+            @NonNull int[] intArray,
+            @NonNull List<String> stringList,
+            @NonNull Map<String,SampleWithCustomBuilder> map,
+            @NonNull Map<String,String> stringMap,
+            @NonNull SparseArray<SampleWithCustomBuilder> sparseArray,
+            @NonNull SparseIntArray sparseIntArray) {
+        this.mStringArray = stringArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mStringArray);
+        this.mIntArray = intArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mIntArray);
+        this.mStringList = stringList;
+        AnnotationValidations.validate(
+                NonNull.class, null, mStringList);
+        this.mMap = map;
+        AnnotationValidations.validate(
+                NonNull.class, null, mMap);
+        this.mStringMap = stringMap;
+        AnnotationValidations.validate(
+                NonNull.class, null, mStringMap);
+        this.mSparseArray = sparseArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mSparseArray);
+        this.mSparseIntArray = sparseIntArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mSparseIntArray);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull String[] getStringArray() {
+        return mStringArray;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull int[] getIntArray() {
+        return mIntArray;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull List<String> getStringList() {
+        return mStringList;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull Map<String,SampleWithCustomBuilder> getMap() {
+        return mMap;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull Map<String,String> getStringMap() {
+        return mStringMap;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull SparseArray<SampleWithCustomBuilder> getSparseArray() {
+        return mSparseArray;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull SparseIntArray getSparseIntArray() {
+        return mSparseIntArray;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "ParcelAllTheThingsDataClass { " +
+                "stringArray = " + java.util.Arrays.toString(mStringArray) + ", " +
+                "intArray = " + java.util.Arrays.toString(mIntArray) + ", " +
+                "stringList = " + mStringList + ", " +
+                "map = " + mMap + ", " +
+                "stringMap = " + mStringMap + ", " +
+                "sparseArray = " + mSparseArray + ", " +
+                "sparseIntArray = " + mSparseIntArray +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeStringArray(mStringArray);
+        dest.writeIntArray(mIntArray);
+        dest.writeStringList(mStringList);
+        dest.writeMap(mMap);
+        dest.writeMap(mStringMap);
+        dest.writeSparseArray(mSparseArray);
+        dest.writeSparseIntArray(mSparseIntArray);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<ParcelAllTheThingsDataClass> CREATOR
+            = new Parcelable.Creator<ParcelAllTheThingsDataClass>() {
+        @Override
+        public ParcelAllTheThingsDataClass[] newArray(int size) {
+            return new ParcelAllTheThingsDataClass[size];
+        }
+
+        @Override
+        @SuppressWarnings({"unchecked", "RedundantCast"})
+        public ParcelAllTheThingsDataClass createFromParcel(Parcel in) {
+            // You can override field unparcelling by defining methods like:
+            // static FieldType unparcelFieldName(Parcel in) { ... }
+
+            String[] stringArray = in.createStringArray();
+            int[] intArray = in.createIntArray();
+            List<String> stringList = new java.util.ArrayList<>();
+            in.readStringList(stringList);
+            Map<String,SampleWithCustomBuilder> map = new java.util.LinkedHashMap<>();
+            in.readMap(map, SampleWithCustomBuilder.class.getClassLoader());
+            Map<String,String> stringMap = new java.util.LinkedHashMap<>();
+            in.readMap(stringMap, String.class.getClassLoader());
+            SparseArray<SampleWithCustomBuilder> sparseArray = (SparseArray) in.readSparseArray(SampleWithCustomBuilder.class.getClassLoader());
+            SparseIntArray sparseIntArray = (SparseIntArray) in.readSparseIntArray();
+            return new ParcelAllTheThingsDataClass(
+                    stringArray,
+                    intArray,
+                    stringList,
+                    map,
+                    stringMap,
+                    sparseArray,
+                    sparseIntArray);
+        }
+    };
+
+    /**
+     * A builder for {@link ParcelAllTheThingsDataClass}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static class Builder {
+
+        private @NonNull String[] mStringArray;
+        private @NonNull int[] mIntArray;
+        private @NonNull List<String> mStringList;
+        private @NonNull Map<String,SampleWithCustomBuilder> mMap;
+        private @NonNull Map<String,String> mStringMap;
+        private @NonNull SparseArray<SampleWithCustomBuilder> mSparseArray;
+        private @NonNull SparseIntArray mSparseIntArray;
+
+        private long mBuilderFieldsSet = 0L;
+
+        public Builder() {
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setStringArray(@NonNull String... value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mStringArray = value;
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setIntArray(@NonNull int... value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mIntArray = value;
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setStringList(@NonNull List<String> value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4;
+            mStringList = value;
+            return this;
+        }
+
+        /** @see #setStringList */
+        @DataClass.Generated.Member
+        public @NonNull Builder addStringList(String value) {
+            // You can refine this method's name by providing item's singular name, e.g.:
+            // @DataClass.PluralOf("item")) mItems = ...
+
+            if (mStringList == null) setStringList(new java.util.ArrayList<>());
+            mStringList.add(value);
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setMap(@NonNull Map<String,SampleWithCustomBuilder> value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x8;
+            mMap = value;
+            return this;
+        }
+
+        /** @see #setMap */
+        @DataClass.Generated.Member
+        public @NonNull Builder addMap(String key, SampleWithCustomBuilder value) {
+            // You can refine this method's name by providing item's singular name, e.g.:
+            // @DataClass.PluralOf("item")) mItems = ...
+
+            if (mMap == null) setMap(new java.util.LinkedHashMap());
+            mMap.put(key, value);
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setStringMap(@NonNull Map<String,String> value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x10;
+            mStringMap = value;
+            return this;
+        }
+
+        /** @see #setStringMap */
+        @DataClass.Generated.Member
+        public @NonNull Builder addStringMap(String key, String value) {
+            // You can refine this method's name by providing item's singular name, e.g.:
+            // @DataClass.PluralOf("item")) mItems = ...
+
+            if (mStringMap == null) setStringMap(new java.util.LinkedHashMap());
+            mStringMap.put(key, value);
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setSparseArray(@NonNull SparseArray<SampleWithCustomBuilder> value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x20;
+            mSparseArray = value;
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setSparseIntArray(@NonNull SparseIntArray value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x40;
+            mSparseIntArray = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public ParcelAllTheThingsDataClass build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x80; // Mark builder used
+
+            if ((mBuilderFieldsSet & 0x1) == 0) {
+                mStringArray = null;
+            }
+            if ((mBuilderFieldsSet & 0x2) == 0) {
+                mIntArray = null;
+            }
+            if ((mBuilderFieldsSet & 0x4) == 0) {
+                mStringList = null;
+            }
+            if ((mBuilderFieldsSet & 0x8) == 0) {
+                mMap = null;
+            }
+            if ((mBuilderFieldsSet & 0x10) == 0) {
+                mStringMap = null;
+            }
+            if ((mBuilderFieldsSet & 0x20) == 0) {
+                mSparseArray = null;
+            }
+            if ((mBuilderFieldsSet & 0x40) == 0) {
+                mSparseIntArray = null;
+            }
+            ParcelAllTheThingsDataClass o = new ParcelAllTheThingsDataClass(
+                    mStringArray,
+                    mIntArray,
+                    mStringList,
+                    mMap,
+                    mStringMap,
+                    mSparseArray,
+                    mSparseIntArray);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x80) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1570139502128L,
+            codegenVersion = "1.0.4",
+            sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java",
+            inputSignatures = " @android.annotation.NonNull java.lang.String[] mStringArray\n @android.annotation.NonNull int[] mIntArray\n @android.annotation.NonNull java.util.List<java.lang.String> mStringList\n @android.annotation.NonNull java.util.Map<java.lang.String,com.android.codegentest.SampleWithCustomBuilder> mMap\n @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.String> mStringMap\n @android.annotation.NonNull android.util.SparseArray<com.android.codegentest.SampleWithCustomBuilder> mSparseArray\n @android.annotation.NonNull android.util.SparseIntArray mSparseIntArray\nclass ParcelAllTheThingsDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)")
+    @Deprecated
+    private void __metadata() {}
+
+}
diff --git a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
index 66c7d06..0631f7d 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
@@ -342,7 +342,7 @@
 
 
 
-    // Code below generated by codegen v1.0.3.
+    // Code below generated by codegen v1.0.4.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -1798,8 +1798,8 @@
     }
 
     @DataClass.Generated(
-            time = 1569956013899L,
-            codegenVersion = "1.0.3",
+            time = 1570139500112L,
+            codegenVersion = "1.0.4",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleDataClass.java",
             inputSignatures = "public static final  java.lang.String STATE_NAME_UNDEFINED\npublic static final  java.lang.String STATE_NAME_ON\npublic static final  java.lang.String STATE_NAME_OFF\npublic static final  int STATE_UNDEFINED\npublic static final  int STATE_ON\npublic static final  int STATE_OFF\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_AUGMENTED_REQUEST\nprivate  int mNum\nprivate  int mNum2\nprivate  int mNum4\nprivate @android.annotation.Nullable java.lang.String mName\nprivate @android.annotation.NonNull java.lang.String mName2\nprivate @android.annotation.NonNull java.lang.String mName4\nprivate @android.annotation.Nullable android.view.accessibility.AccessibilityNodeInfo mOtherParcelable\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.codegentest.MyDateParcelling.class) @android.annotation.NonNull java.util.Date mDate\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForPattern.class) @android.annotation.NonNull java.util.regex.Pattern mPattern\nprivate @android.annotation.NonNull java.util.List<android.net.LinkAddress> mLinkAddresses2\nprivate @com.android.internal.util.DataClass.PluralOf(\"linkAddress\") @android.annotation.NonNull java.util.ArrayList<android.net.LinkAddress> mLinkAddresses\nprivate @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses4\nprivate @com.android.codegentest.SampleDataClass.StateName @android.annotation.NonNull java.lang.String mStateName\nprivate @com.android.codegentest.SampleDataClass.RequestFlags int mFlags\nprivate @com.android.codegentest.SampleDataClass.State int mState\npublic @android.annotation.NonNull java.lang.CharSequence charSeq\nprivate final @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses5\nprivate transient  android.net.LinkAddress[] mLinkAddresses6\ntransient  int[] mTmpStorage\nprivate @android.annotation.StringRes int mStringRes\nprivate @android.annotation.IntRange(from=0L, to=6L) int mDayOfWeek\nprivate @android.annotation.Size(2L) @android.annotation.NonNull @com.android.internal.util.DataClass.Each @android.annotation.FloatRange(from=0.0) float[] mCoords\nprivate static  java.lang.String defaultName4()\nprivate  int[] lazyInitTmpStorage()\npublic  android.net.LinkAddress[] getLinkAddresses4()\nprivate  boolean patternEquals(java.util.regex.Pattern)\nprivate  int patternHashCode()\nprivate  void onConstructed()\npublic  void dump(java.io.PrintWriter)\nclass SampleDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=true, genEqualsHashCode=true, genToString=true, genForEachField=true, genSetters=true)")
     @Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleDataClassTest.java b/tests/Codegen/src/com/android/codegentest/SampleDataClassTest.java
index 6636207..c7a7735 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleDataClassTest.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleDataClassTest.java
@@ -25,9 +25,14 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertThat;
 
+import static java.util.concurrent.TimeUnit.SECONDS;
+
 import android.net.LinkAddress;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -36,6 +41,9 @@
 
 import java.util.Arrays;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -209,6 +217,32 @@
         newBuilder().setDayOfWeek(42).build();
     }
 
+    @Test
+    public void testDataStructures_parcelCorrectly() {
+        SampleWithCustomBuilder otherParcelable = new SampleWithCustomBuilder.Builder().setDelay(3, SECONDS).build();
+
+        ParcelAllTheThingsDataClass instance = new ParcelAllTheThingsDataClass.Builder()
+                .setIntArray(40, 41)
+                .addMap("foo", otherParcelable)
+                .setSparseArray(new SparseArray<SampleWithCustomBuilder>() {{
+                    put(45, otherParcelable);
+                }})
+                .setSparseIntArray(new SparseIntArray() {{
+                    put(48, 49);
+                }})
+                .addStringMap("foo2", "fooValue")
+                .setStringArray("foo", "bar")
+                .addStringList("foo")
+                .build();
+
+        ParcelAllTheThingsDataClass unparceledInstance =
+                parcelAndUnparcel(instance, ParcelAllTheThingsDataClass.CREATOR);
+
+        // SparseArray and friends don't implement equals
+        // so just compare string representations instead
+        assertEquals(instance.toString(), unparceledInstance.toString());
+    }
+
     private static <T extends Parcelable> T parcelAndUnparcel(
             T original, Parcelable.Creator<T> creator) {
         Parcel p = Parcel.obtain();
diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
index c6bc8de..0f8c663 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
@@ -17,14 +17,16 @@
 package com.android.codegentest;
 
 import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.SystemClock;
 
 import com.android.internal.util.DataClass;
 
 import java.util.concurrent.TimeUnit;
 
-@DataClass(genBuilder = true)
-public class SampleWithCustomBuilder {
+@DataClass(genBuilder = true, genAidl = false, genToString = true)
+public class SampleWithCustomBuilder implements Parcelable {
 
     long delayAmount = 0;
     @NonNull
@@ -73,8 +75,17 @@
     }
 
 
+    private static TimeUnit unparcelDelayUnit(Parcel p) {
+        return TimeUnit.values()[p.readInt()];
+    }
 
-    // Code below generated by codegen v1.0.3.
+    private void parcelDelayUnit(Parcel p, int flags) {
+        p.writeInt(delayUnit.ordinal());
+    }
+
+
+
+    // Code below generated by codegen v1.0.4.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -112,6 +123,58 @@
         return creationTimestamp;
     }
 
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "SampleWithCustomBuilder { " +
+                "delayAmount = " + delayAmount + ", " +
+                "delayUnit = " + delayUnit + ", " +
+                "creationTimestamp = " + creationTimestamp +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeLong(delayAmount);
+        parcelDelayUnit(dest, flags);
+        dest.writeLong(creationTimestamp);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<SampleWithCustomBuilder> CREATOR
+            = new Parcelable.Creator<SampleWithCustomBuilder>() {
+        @Override
+        public SampleWithCustomBuilder[] newArray(int size) {
+            return new SampleWithCustomBuilder[size];
+        }
+
+        @Override
+        @SuppressWarnings({"unchecked", "RedundantCast"})
+        public SampleWithCustomBuilder createFromParcel(Parcel in) {
+            // You can override field unparcelling by defining methods like:
+            // static FieldType unparcelFieldName(Parcel in) { ... }
+
+            long _delayAmount = in.readLong();
+            TimeUnit _delayUnit = unparcelDelayUnit(in);
+            long _creationTimestamp = in.readLong();
+            return new SampleWithCustomBuilder(
+                    _delayAmount,
+                    _delayUnit,
+                    _creationTimestamp);
+        }
+    };
+
     /**
      * A builder for {@link SampleWithCustomBuilder}
      */
@@ -176,10 +239,10 @@
     }
 
     @DataClass.Generated(
-            time = 1569956014908L,
-            codegenVersion = "1.0.3",
+            time = 1570139501160L,
+            codegenVersion = "1.0.4",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java",
-            inputSignatures = "  long delayAmount\n @android.annotation.NonNull java.util.concurrent.TimeUnit delayUnit\n  long creationTimestamp\nclass SampleWithCustomBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true)\nabstract  com.android.codegentest.SampleWithCustomBuilder.Builder setDelayAmount(long)\npublic abstract  com.android.codegentest.SampleWithCustomBuilder.Builder setDelayUnit(java.util.concurrent.TimeUnit)\npublic  com.android.codegentest.SampleWithCustomBuilder.Builder setDelay(long,java.util.concurrent.TimeUnit)\nclass BaseBuilder extends java.lang.Object implements []")
+            inputSignatures = "  long delayAmount\n @android.annotation.NonNull java.util.concurrent.TimeUnit delayUnit\n  long creationTimestamp\nprivate static  java.util.concurrent.TimeUnit unparcelDelayUnit(android.os.Parcel)\nprivate  void parcelDelayUnit(android.os.Parcel,int)\nclass SampleWithCustomBuilder extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)\nabstract  com.android.codegentest.SampleWithCustomBuilder.Builder setDelayAmount(long)\npublic abstract  com.android.codegentest.SampleWithCustomBuilder.Builder setDelayUnit(java.util.concurrent.TimeUnit)\npublic  com.android.codegentest.SampleWithCustomBuilder.Builder setDelay(long,java.util.concurrent.TimeUnit)\nclass BaseBuilder extends java.lang.Object implements []")
     @Deprecated
     private void __metadata() {}