script-astra/Android/Sdk/sources/android-35/android/app/appsearch/safeparcel/SafeParcelable.java
localadmin 4380f00a78 init
2025-01-20 18:15:20 +03:00

318 lines
14 KiB
Java

/*
* Copyright (C) 2023 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 android.app.appsearch.safeparcel;
import android.os.Parcel;
import android.os.Parcelable;
/**
* A SafeParcelable is a special {@link Parcelable} interface that marshalls its fields in a
* protobuf-like manner into a {@link Parcel}. The marshalling encodes a unique id for each field
* along with the size in bytes of the field. By doing this, older versions of a SafeParcelable can
* skip over unknown fields, which enables backwards compatibility. Because SafeParcelable extends a
* Parcelable, it is NOT safe for persistence.
*
* <p>To prevent the need to manually write code to marshall fields like in a Parcelable, a
* SafeParcelable implementing class is annotated with several annotations so that a generated
* "creator" class has the metadata it needs to automatically generate the boiler plate marshalling
* and unmarshalling code.
*
* <p>The main annotations are the following:
*
* <ul>
* <li>{@link Class} - This annotates the SafeParcelable implementing class and indicates the name
* of the generated "creator" class that has the boiler plate marshalling/unmarshalling code.
* You can also specify whether to call a method named validateContents() after a new instance
* of this class is constructed.
* <li>{@link VersionField} - This annotation may be on one field in the SafeParcelable to
* indicate the version number for this SafeParcelable. This is purely here for style reasons
* in case it is necessary for code to be dependent on the version of the SafeParcelable. This
* member field must be final.
* <li>{@link Field} - This annotates fields that will be marshalled and unmarshalled by the
* generated "creator" class. You must provide an integer "id" for each field. To ensure
* backwards compatibility, these field id's should never be changed. It is okay to omit field
* id's in future versions, but do not reuse old id's. Member fields annotated with {@link
* Field} may be any visibility (private, protected, etc.) and may also be final. You will
* have to specify the "getter" if member fields are not at least package visible. See details
* in {@link Field}.
* <li>{@link Constructor} - You must annotate one constructor with this annotation, which
* indicates the constructor that the "creator" class will use to construct a new instance of
* this class. Each parameter to this constructor must be annotated with the {@link Param} or
* {@link RemovedParam} annotation indicating the field id that the parameter corresponds to.
* Every {@link Param} must correspond to a {@link Field} or {@link VersionField}, and every
* {@link RemovedParam} must correspond to a {@link Reserved} field. Note that this
* constructor must have at least package visibility because the generated "creator" class
* must be able to use this constructor. (The "creator" class is generated in the same package
* as the SafeParcelable class.).
* <li>{@link Indicator} - This is an annotation on a field that keeps track of which fields are
* actually present in a Parcel that represents the marshalled version of a SafeParcelable.
* This is used in the GMS Core Apiary model class code generation.
* </ul>
*
* <p>Because a SafeParcelable extends Parcelable, you must have a public static final member named
* CREATOR and override writeToParcel() and describeContents(). Here's a typical example.
*
* <pre>
* &#64;Class(creator="MySafeParcelableCreator", validate=true)
* public class MySafeParcelable implements SafeParcelable {
* public static final Parcelable.Creator&#60;MySafeParcelable&#62; CREATOR =
* new MySafeParcelableCreator();
*
* &#64;Field(id=1)
* public final String myString;
*
* &#64;Field(id=2, getter="getInteger")
* private final int myInteger;
*
* &#64;Constructor
* MySafeParcelable(
* &#64;Param(id=1) String string,
* &#64;Param(id=2) int integer) {
* myString = string;
* myInteger = integer;
* )
*
* // Example public constructor (not used by MySafeParcelableCreator)
* public MySafeParcelable(String string, int integer) {
* myString = string;
* myInteger = integer;
* }
*
* // This is only needed if validate=true in &#64;Class annotation.
* public void validateContents() {
* // Add validation here.
* }
*
* // This getter is needed because myInteger is private, and the generated creator class
* // MySafeParcelableCreator can't access private member fields.
* int getInteger() {
* return myInteger;
* }
*
* // This is necessary because SafeParcelable extends Parcelable.
* // {@link AbstractSafeParcelable} implements this for you.
* &#64;Override
* public int describeContents() {
* return MySafeParcelableCreator.CONTENT_DESCRIPTION;
* }
*
* // This is necessary because SafeParcelable extends Parcelable.
* &#64;Override
* public void writeToParcel(Parcel out, int flags) {
* // This invokes the generated MySafeParcelableCreator class's marshalling to a Parcel.
* // In the event you need custom logic when writing to a Parcel, that logic can be
* // inserted here.
* MySafeParcelableCreator.writeToParcel(this, out, flags);
* }
* }
* </pre>
*
* @hide
*/
// Include the SafeParcel source code directly in AppSearch until it gets officially open-sourced.
public interface SafeParcelable extends Parcelable {
/** @hide */
// Note: the field name and value are accessed using reflection for backwards compatibility, and
// must not be changed.
String NULL = "SAFE_PARCELABLE_NULL_STRING";
/**
* This annotates your class and specifies the name of the generated "creator" class for
* marshalling/unmarshalling a SafeParcelable to/from a {@link Parcel}. The "creator" class is
* generated in the same package as the SafeParcelable class. You can also set "validate" to
* true, which will cause the "creator" to invoke the method validateContents() on your class
* after constructing an instance.
*/
@SuppressWarnings("JavaLangClash")
@interface Class {
/**
* Simple name of the generated "creator" class generated in the same package as the
* SafeParceable.
*/
String creator();
/** Whether the generated "creator" class is final. */
boolean creatorIsFinal() default true;
/**
* When set to true, invokes the validateContents() method in this SafeParcelable object
* after constructing a new instance.
*/
boolean validate() default false;
/**
* When set to true, it will not write type default values to the Parcel.
*
* <p>boolean: false byte/char/short/int/long: 0 float: 0.0f double: 0.0 Objects/arrays:
* null
*
* <p>Cannot be used with Field(defaultValue)
*/
boolean doNotParcelTypeDefaultValues() default false;
}
/** Use this annotation on members that you wish to be marshalled in the SafeParcelable. */
@interface Field {
/**
* Valid values for id are between 1 and 65535. This field id is marshalled into a Parcel .
* To maintain backwards compatibility, never reuse old id's. It is okay to no longer use
* old id's and add new ones in subsequent versions of a SafeParcelable.
*/
int id();
/**
* This specifies the name of the getter method for retrieving the value of this field. This
* must be specified for fields that do not have at least package visibility because the
* "creator" class will be unable to access the value when attempting to marshall this
* field. The getter method should take no parameters and return the type of this field
* (unless overridden by the "type" attribute below).
*/
String getter() default NULL;
/**
* For advanced uses, this specifies the type for the field when marshalling and
* unmarshalling by the "creator" class to be something different than the declared type of
* the member variable. This is useful if you want to incorporate an object that is not
* SafeParcelable (or a system Parcelable object). Be sure to enter the fully qualified name
* for the class (i.e., android.os.Bundle and not Bundle). For example,
*
* <pre>
* &#64;Class(creator="MyAdvancedCreator")
* public class MyAdvancedSafeParcelable implements SafeParcelable {
* public static final Parcelable.Creator&#60;MyAdvancedSafeParcelable&#62; CREATOR =
* new MyAdvancedCreator();
*
* &#64;Field(id=1, getter="getObjectAsBundle", type="android.os.Bundle")
* private final MyCustomObject myObject;
*
* &#64;Constructor
* MyAdvancedSafeParcelable(
* &#64;Param(id=1) Bundle objectAsBundle) {
* myObject = myConvertFromBundleToObject(objectAsBundle);
* }
*
* Bundle getObjectAsBundle() {
* // The code here can convert your custom object to one that can be parcelled.
* return myConvertFromObjectToBundle(myObject);
* }
*
* ...
* }
* </pre>
*/
String type() default NULL;
/**
* This can be used to specify the default value for primitive types (e.g., boolean, int,
* long), primitive type object wrappers (e.g., Boolean, Integer, Long) and String in the
* case a value for a field was not explicitly set in the marshalled Parcel. This performs
* compile-time checks for the type of the field and inserts the appropriate quotes or
* double quotes around strings and chars or removes them completely for booleans and
* numbers. To insert a generic string for initializing field, use {@link
* #defaultValueUnchecked()}. You can specify at most one of {@link #defaultValue()} or
* {@link #defaultValueUnchecked()}. For example,
*
* <pre>
* &#64;Field(id=2, defaultValue="true")
* boolean myBoolean;
*
* &#64;Field(id=3, defaultValue="13")
* Integer myInteger;
*
* &#64;Field(id=4, defaultValue="foo")
* String myString;
* </pre>
*/
String defaultValue() default NULL;
/**
* This can be used to specify the default value for any object and the string value is
* literally added to the generated creator class code unchecked. You can specify at most
* one of {@link #defaultValue()} or {@link #defaultValueUnchecked()}. You must fully
* qualify any classes you reference within the string. For example,
*
* <pre>
* &#64;Field(id=2, defaultValueUnchecked="new android.os.Bundle()")
* Bundle myBundle;
* </pre>
*/
String defaultValueUnchecked() default NULL;
}
/**
* There may be exactly one member annotated with VersionField, which represents the version of
* this safe parcelable. The attributes are the same as those of {@link Field}. Note you can use
* any type you want for your version field, although most people use int's.
*/
@interface VersionField {
int id();
String getter() default NULL;
String type() default NULL;
}
/**
* Use this to indicate the member field that holds whether a field was set or not. The member
* field type currently supported is a HashSet&#60;Integer&#62; which is the set of safe
* parcelable field id's that have been explicitly set.
*
* <p>This annotation should also be used to annotate one of the parameters to the constructor
* annotated with &#64;Constructor. Note that this annotation should either be present on
* exactly one member field and one constructor parameter or left out completely.
*/
@interface Indicator {
String getter() default NULL;
}
/**
* Use this to indicate the constructor that the creator should use. The constructor annotated
* with this must be package or public visibility, so that the generated "creator" class can
* invoke this.
*/
@interface Constructor {}
/**
* Use this on each parameter passed in to the Constructor to indicate to which field id each
* formal parameter corresponds.
*/
@interface Param {
int id();
}
/**
* Use this on a parameter passed in to the Constructor to indicate that a removed field should
* be read on construction. If the field is not present when read, the default value will be
* used instead.
*/
@interface RemovedParam {
int id();
String defaultValue() default NULL;
String defaultValueUnchecked() default NULL;
}
/**
* Use this to mark tombstones for removed {@link Field Fields} or {@link VersionField
* VersionFields}.
*/
@interface Reserved {
int[] value();
}
}