/*
* Copyright (C) 2020 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.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.util.MathUtils;
/**
* ParcelableHolder is a Parcelable which can contain another Parcelable.
* The main use case of ParcelableHolder is to make a Parcelable extensible.
* For example, an AOSP-defined Parcelable AospDefinedParcelable
* is expected to be extended by device implementers for their value-add features.
* Previously without ParcelableHolder, the device implementers had to
* directly modify the Parcelable to add more fields:
*
{@code
* parcelable AospDefinedParcelable {
* int a;
* String b;
* String x; // added by a device implementer
* int[] y; // added by a device implementer
* }}
*
* This practice is very error-prone because the fields added by the device implementer
* might have a conflict when the Parcelable is revisioned in the next releases of Android.
*
* Using ParcelableHolder, one can define an extension point in a Parcelable.
* {@code
* parcelable AospDefinedParcelable {
* int a;
* String b;
* ParcelableHolder extension;
* }}
* Then the device implementers can define their own Parcelable for their extension.
*
* {@code
* parcelable OemDefinedParcelable {
* String x;
* int[] y;
* }}
* Finally, the new Parcelable can be attached to the original Parcelable via
* the ParcelableHolder field.
*
* {@code
* AospDefinedParcelable ap = ...;
* OemDefinedParcelable op = new OemDefinedParcelable();
* op.x = ...;
* op.y = ...;
* ap.extension.setParcelable(op);}
*
* @hide
*/
@SystemApi
public final class ParcelableHolder implements Parcelable {
/**
* This is set by {@link #setParcelable}.
* {@link #mParcelable} and {@link #mParcel} are mutually exclusive
* if {@link ParcelableHolder} contains value, otherwise, both are null.
*/
private Parcelable mParcelable;
/**
* This is set by {@link #readFromParcel}.
* {@link #mParcelable} and {@link #mParcel} are mutually exclusive
* if {@link ParcelableHolder} contains value, otherwise, both are null.
*/
private Parcel mParcel;
private @Parcelable.Stability int mStability = Parcelable.PARCELABLE_STABILITY_LOCAL;
public ParcelableHolder(@Parcelable.Stability int stability) {
mStability = stability;
}
private ParcelableHolder() {
}
/**
* {@link ParcelableHolder}'s stability is determined by the parcelable
* which contains this ParcelableHolder.
* For more detail refer to {@link Parcelable#getStability}.
*/
@Override
public @Parcelable.Stability int getStability() {
return mStability;
}
@NonNull
public static final Parcelable.Creator