1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app.appsearch.safeparcel;
18 
19 import android.os.Parcel;
20 import android.os.Parcelable;
21 
22 /**
23  * A SafeParcelable is a special {@link Parcelable} interface that marshalls its fields in a
24  * protobuf-like manner into a {@link Parcel}. The marshalling encodes a unique id for each field
25  * along with the size in bytes of the field. By doing this, older versions of a SafeParcelable can
26  * skip over unknown fields, which enables backwards compatibility. Because SafeParcelable extends a
27  * Parcelable, it is NOT safe for persistence.
28  *
29  * <p>To prevent the need to manually write code to marshall fields like in a Parcelable, a
30  * SafeParcelable implementing class is annotated with several annotations so that a generated
31  * "creator" class has the metadata it needs to automatically generate the boiler plate marshalling
32  * and unmarshalling code.
33  *
34  * <p>The main annotations are the following:
35  *
36  * <ul>
37  *   <li>{@link Class} - This annotates the SafeParcelable implementing class and indicates the name
38  *       of the generated "creator" class that has the boiler plate marshalling/unmarshalling code.
39  *       You can also specify whether to call a method named validateContents() after a new instance
40  *       of this class is constructed.
41  *   <li>{@link VersionField} - This annotation may be on one field in the SafeParcelable to
42  *       indicate the version number for this SafeParcelable. This is purely here for style reasons
43  *       in case it is necessary for code to be dependent on the version of the SafeParcelable. This
44  *       member field must be final.
45  *   <li>{@link Field} - This annotates fields that will be marshalled and unmarshalled by the
46  *       generated "creator" class. You must provide an integer "id" for each field. To ensure
47  *       backwards compatibility, these field id's should never be changed. It is okay to omit field
48  *       id's in future versions, but do not reuse old id's. Member fields annotated with {@link
49  *       Field} may be any visibility (private, protected, etc.) and may also be final. You will
50  *       have to specify the "getter" if member fields are not at least package visible. See details
51  *       in {@link Field}.
52  *   <li>{@link Constructor} - You must annotate one constructor with this annotation, which
53  *       indicates the constructor that the "creator" class will use to construct a new instance of
54  *       this class. Each parameter to this constructor must be annotated with the {@link Param} or
55  *       {@link RemovedParam} annotation indicating the field id that the parameter corresponds to.
56  *       Every {@link Param} must correspond to a {@link Field} or {@link VersionField}, and every
57  *       {@link RemovedParam} must correspond to a {@link Reserved} field. Note that this
58  *       constructor must have at least package visibility because the generated "creator" class
59  *       must be able to use this constructor. (The "creator" class is generated in the same package
60  *       as the SafeParcelable class.).
61  *   <li>{@link Indicator} - This is an annotation on a field that keeps track of which fields are
62  *       actually present in a Parcel that represents the marshalled version of a SafeParcelable.
63  *       This is used in the GMS Core Apiary model class code generation.
64  * </ul>
65  *
66  * <p>Because a SafeParcelable extends Parcelable, you must have a public static final member named
67  * CREATOR and override writeToParcel() and describeContents(). Here's a typical example.
68  *
69  * <pre>
70  *   &#64;Class(creator="MySafeParcelableCreator", validate=true)
71  *   public class MySafeParcelable implements SafeParcelable {
72  *       public static final Parcelable.Creator&#60;MySafeParcelable&#62; CREATOR =
73  *               new MySafeParcelableCreator();
74  *
75  *       &#64;Field(id=1)
76  *       public final String myString;
77  *
78  *       &#64;Field(id=2, getter="getInteger")
79  *       private final int myInteger;
80  *
81  *       &#64;Constructor
82  *       MySafeParcelable(
83  *               &#64;Param(id=1) String string,
84  *               &#64;Param(id=2) int integer) {
85  *           myString = string;
86  *           myInteger = integer;
87  *       )
88  *
89  *       // Example public constructor (not used by MySafeParcelableCreator)
90  *       public MySafeParcelable(String string, int integer) {
91  *           myString = string;
92  *           myInteger = integer;
93  *       }
94  *
95  *       // This is only needed if validate=true in &#64;Class annotation.
96  *       public void validateContents() {
97  *           // Add validation here.
98  *       }
99  *
100  *       // This getter is needed because myInteger is private, and the generated creator class
101  *       // MySafeParcelableCreator can't access private member fields.
102  *       int getInteger() {
103  *           return myInteger;
104  *       }
105  *
106  *       // This is necessary because SafeParcelable extends Parcelable.
107  *       // {@link AbstractSafeParcelable} implements this for you.
108  *       &#64;Override
109  *       public int describeContents() {
110  *           return MySafeParcelableCreator.CONTENT_DESCRIPTION;
111  *       }
112  *
113  *       // This is necessary because SafeParcelable extends Parcelable.
114  *       &#64;Override
115  *       public void writeToParcel(Parcel out, int flags) {
116  *           // This invokes the generated MySafeParcelableCreator class's marshalling to a Parcel.
117  *           // In the event you need custom logic when writing to a Parcel, that logic can be
118  *           // inserted here.
119  *           MySafeParcelableCreator.writeToParcel(this, out, flags);
120  *       }
121  *   }
122  * </pre>
123  *
124  * @hide
125  */
126 // Include the SafeParcel source code directly in AppSearch until it gets officially open-sourced.
127 public interface SafeParcelable extends Parcelable {
128     /** @hide */
129     // Note: the field name and value are accessed using reflection for backwards compatibility, and
130     // must not be changed.
131     String NULL = "SAFE_PARCELABLE_NULL_STRING";
132 
133     /**
134      * This annotates your class and specifies the name of the generated "creator" class for
135      * marshalling/unmarshalling a SafeParcelable to/from a {@link Parcel}. The "creator" class is
136      * generated in the same package as the SafeParcelable class. You can also set "validate" to
137      * true, which will cause the "creator" to invoke the method validateContents() on your class
138      * after constructing an instance.
139      */
140     @SuppressWarnings("JavaLangClash")
141     @interface Class {
142         /**
143          * Simple name of the generated "creator" class generated in the same package as the
144          * SafeParceable.
145          */
creator()146         String creator();
147 
148         /** Whether the generated "creator" class is final. */
creatorIsFinal()149         boolean creatorIsFinal() default true;
150 
151         /**
152          * When set to true, invokes the validateContents() method in this SafeParcelable object
153          * after constructing a new instance.
154          */
validate()155         boolean validate() default false;
156 
157         /**
158          * When set to true, it will not write type default values to the Parcel.
159          *
160          * <p>boolean: false byte/char/short/int/long: 0 float: 0.0f double: 0.0 Objects/arrays:
161          * null
162          *
163          * <p>Cannot be used with Field(defaultValue)
164          */
doNotParcelTypeDefaultValues()165         boolean doNotParcelTypeDefaultValues() default false;
166     }
167 
168     /** Use this annotation on members that you wish to be marshalled in the SafeParcelable. */
169     @interface Field {
170         /**
171          * Valid values for id are between 1 and 65535. This field id is marshalled into a Parcel .
172          * To maintain backwards compatibility, never reuse old id's. It is okay to no longer use
173          * old id's and add new ones in subsequent versions of a SafeParcelable.
174          */
id()175         int id();
176 
177         /**
178          * This specifies the name of the getter method for retrieving the value of this field. This
179          * must be specified for fields that do not have at least package visibility because the
180          * "creator" class will be unable to access the value when attempting to marshall this
181          * field. The getter method should take no parameters and return the type of this field
182          * (unless overridden by the "type" attribute below).
183          */
getter()184         String getter() default NULL;
185 
186         /**
187          * For advanced uses, this specifies the type for the field when marshalling and
188          * unmarshalling by the "creator" class to be something different than the declared type of
189          * the member variable. This is useful if you want to incorporate an object that is not
190          * SafeParcelable (or a system Parcelable object). Be sure to enter the fully qualified name
191          * for the class (i.e., android.os.Bundle and not Bundle). For example,
192          *
193          * <pre>
194          *   &#64;Class(creator="MyAdvancedCreator")
195          *   public class MyAdvancedSafeParcelable implements SafeParcelable {
196          *       public static final Parcelable.Creator&#60;MyAdvancedSafeParcelable&#62; CREATOR =
197          *               new MyAdvancedCreator();
198          *
199          *       &#64;Field(id=1, getter="getObjectAsBundle", type="android.os.Bundle")
200          *       private final MyCustomObject myObject;
201          *
202          *       &#64;Constructor
203          *       MyAdvancedSafeParcelable(
204          *               &#64;Param(id=1) Bundle objectAsBundle) {
205          *           myObject = myConvertFromBundleToObject(objectAsBundle);
206          *       }
207          *
208          *       Bundle getObjectAsBundle() {
209          *           // The code here can convert your custom object to one that can be parcelled.
210          *           return myConvertFromObjectToBundle(myObject);
211          *       }
212          *
213          *       ...
214          *   }
215          * </pre>
216          */
type()217         String type() default NULL;
218 
219         /**
220          * This can be used to specify the default value for primitive types (e.g., boolean, int,
221          * long), primitive type object wrappers (e.g., Boolean, Integer, Long) and String in the
222          * case a value for a field was not explicitly set in the marshalled Parcel. This performs
223          * compile-time checks for the type of the field and inserts the appropriate quotes or
224          * double quotes around strings and chars or removes them completely for booleans and
225          * numbers. To insert a generic string for initializing field, use {@link
226          * #defaultValueUnchecked()}. You can specify at most one of {@link #defaultValue()} or
227          * {@link #defaultValueUnchecked()}. For example,
228          *
229          * <pre>
230          *   &#64;Field(id=2, defaultValue="true")
231          *   boolean myBoolean;
232          *
233          *   &#64;Field(id=3, defaultValue="13")
234          *   Integer myInteger;
235          *
236          *   &#64;Field(id=4, defaultValue="foo")
237          *   String myString;
238          * </pre>
239          */
defaultValue()240         String defaultValue() default NULL;
241 
242         /**
243          * This can be used to specify the default value for any object and the string value is
244          * literally added to the generated creator class code unchecked. You can specify at most
245          * one of {@link #defaultValue()} or {@link #defaultValueUnchecked()}. You must fully
246          * qualify any classes you reference within the string. For example,
247          *
248          * <pre>
249          *   &#64;Field(id=2, defaultValueUnchecked="new android.os.Bundle()")
250          *   Bundle myBundle;
251          * </pre>
252          */
defaultValueUnchecked()253         String defaultValueUnchecked() default NULL;
254     }
255 
256     /**
257      * There may be exactly one member annotated with VersionField, which represents the version of
258      * this safe parcelable. The attributes are the same as those of {@link Field}. Note you can use
259      * any type you want for your version field, although most people use int's.
260      */
261     @interface VersionField {
id()262         int id();
263 
getter()264         String getter() default NULL;
265 
type()266         String type() default NULL;
267     }
268 
269     /**
270      * Use this to indicate the member field that holds whether a field was set or not. The member
271      * field type currently supported is a HashSet&#60;Integer&#62; which is the set of safe
272      * parcelable field id's that have been explicitly set.
273      *
274      * <p>This annotation should also be used to annotate one of the parameters to the constructor
275      * annotated with &#64;Constructor. Note that this annotation should either be present on
276      * exactly one member field and one constructor parameter or left out completely.
277      */
278     @interface Indicator {
getter()279         String getter() default NULL;
280     }
281 
282     /**
283      * Use this to indicate the constructor that the creator should use. The constructor annotated
284      * with this must be package or public visibility, so that the generated "creator" class can
285      * invoke this.
286      */
287     @interface Constructor {}
288 
289     /**
290      * Use this on each parameter passed in to the Constructor to indicate to which field id each
291      * formal parameter corresponds.
292      */
293     @interface Param {
id()294         int id();
295     }
296 
297     /**
298      * Use this on a parameter passed in to the Constructor to indicate that a removed field should
299      * be read on construction. If the field is not present when read, the default value will be
300      * used instead.
301      */
302     @interface RemovedParam {
id()303         int id();
304 
defaultValue()305         String defaultValue() default NULL;
306 
defaultValueUnchecked()307         String defaultValueUnchecked() default NULL;
308     }
309 
310     /**
311      * Use this to mark tombstones for removed {@link Field Fields} or {@link VersionField
312      * VersionFields}.
313      */
314     @interface Reserved {
value()315         int[] value();
316     }
317 }
318