VersionedParcelParcel.java
/*
* Copyright 2018 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 androidx.versionedparcelable;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import android.util.SparseIntArray;
import androidx.annotation.RestrictTo;
/**
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
class VersionedParcelParcel extends VersionedParcel {
private static final boolean DEBUG = false;
private static final String TAG = "VersionedParcelParcel";
private final SparseIntArray mPositionLookup = new SparseIntArray();
private final Parcel mParcel;
private final int mOffset;
private final int mEnd;
private final String mPrefix;
private int mCurrentField = -1;
private int mNextRead = 0;
VersionedParcelParcel(Parcel p) {
this(p, p.dataPosition(), p.dataSize(), "");
}
VersionedParcelParcel(Parcel p, int offset, int end, String prefix) {
mParcel = p;
mOffset = offset;
mEnd = end;
mNextRead = mOffset;
mPrefix = prefix;
}
private int readUntilField(int fieldId) {
while (mNextRead < mEnd) {
mParcel.setDataPosition(mNextRead);
int size = mParcel.readInt();
int fid = mParcel.readInt();
if (DEBUG) Log.d(TAG, mPrefix + "Found field " + fieldId + " : " + size);
mNextRead = mNextRead + size;
if (fid == fieldId) return mParcel.dataPosition();
}
return -1;
}
@Override
public boolean readField(int fieldId) {
int position = readUntilField(fieldId);
if (position == -1) {
return false;
}
if (DEBUG) Log.d(TAG, mPrefix + "Reading " + fieldId + " : " + position);
mParcel.setDataPosition(position);
return true;
}
@Override
public void setOutputField(int fieldId) {
closeField();
mCurrentField = fieldId;
mPositionLookup.put(fieldId, mParcel.dataPosition());
if (DEBUG) Log.d(TAG, mPrefix + "Starting " + fieldId + " : " + mParcel.dataPosition());
writeInt(0); // Placeholder for field size
writeInt(fieldId);
}
@Override
public void closeField() {
if (mCurrentField >= 0) {
int currentFieldPosition = mPositionLookup.get(mCurrentField);
int position = mParcel.dataPosition();
int size = position - currentFieldPosition;
if (DEBUG) {
Log.d(TAG, mPrefix + "Closing " + mCurrentField + " : "
+ mParcel.dataPosition() + " " + size);
}
mParcel.setDataPosition(currentFieldPosition);
mParcel.writeInt(size);
mParcel.setDataPosition(position);
}
}
@Override
protected VersionedParcel createSubParcel() {
if (DEBUG) {
Log.d(TAG, mPrefix + "Creating subparcel " + mCurrentField + " : "
+ mParcel.dataPosition() + " - " + (mNextRead == mOffset ? mEnd : mNextRead));
}
return new VersionedParcelParcel(mParcel, mParcel.dataPosition(),
mNextRead == mOffset ? mEnd : mNextRead, mPrefix + " ");
}
@Override
public void writeByteArray(byte[] b) {
if (b != null) {
mParcel.writeInt(b.length);
mParcel.writeByteArray(b);
} else {
mParcel.writeInt(-1);
}
}
@Override
public void writeByteArray(byte[] b, int offset, int len) {
if (b != null) {
mParcel.writeInt(b.length);
mParcel.writeByteArray(b, offset, len);
} else {
mParcel.writeInt(-1);
}
}
@Override
public void writeInt(int val) {
mParcel.writeInt(val);
}
@Override
public void writeLong(long val) {
mParcel.writeLong(val);
}
@Override
public void writeFloat(float val) {
mParcel.writeFloat(val);
}
@Override
public void writeDouble(double val) {
mParcel.writeDouble(val);
}
@Override
public void writeString(String val) {
mParcel.writeString(val);
}
@Override
public void writeStrongBinder(IBinder val) {
mParcel.writeStrongBinder(val);
}
@Override
public void writeParcelable(Parcelable p) {
mParcel.writeParcelable(p, 0);
}
@Override
public void writeBoolean(boolean val) {
mParcel.writeInt(val ? 1 : 0);
}
@Override
public void writeStrongInterface(IInterface val) {
mParcel.writeStrongInterface(val);
}
@Override
public void writeBundle(Bundle val) {
mParcel.writeBundle(val);
}
@Override
public int readInt() {
return mParcel.readInt();
}
@Override
public long readLong() {
return mParcel.readLong();
}
@Override
public float readFloat() {
return mParcel.readFloat();
}
@Override
public double readDouble() {
return mParcel.readDouble();
}
@Override
public String readString() {
return mParcel.readString();
}
@Override
public IBinder readStrongBinder() {
return mParcel.readStrongBinder();
}
@Override
public byte[] readByteArray() {
int len = mParcel.readInt();
if (len < 0) {
return null;
}
byte[] bytes = new byte[len];
mParcel.readByteArray(bytes);
return bytes;
}
@Override
@SuppressWarnings("TypeParameterUnusedInFormals")
public <T extends Parcelable> T readParcelable() {
return mParcel.readParcelable(getClass().getClassLoader());
}
@Override
public Bundle readBundle() {
return mParcel.readBundle(getClass().getClassLoader());
}
@Override
public boolean readBoolean() {
return mParcel.readInt() != 0;
}
}