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

931 lines
30 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.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.SparseLongArray;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
/**
* Functions to read in a safe parcel.
*
* @hide
*/
// Include the SafeParcel source code directly in AppSearch until it gets officially open-sourced.
public class SafeParcelReader {
/** class to parse the exception. */
public static class ParseException extends RuntimeException {
public ParseException(@NonNull String message, @NonNull Parcel p) {
super(message + " Parcel: pos=" + p.dataPosition() + " size=" + p.dataSize());
}
}
private SafeParcelReader() {}
/** Reads the header. */
public static int readHeader(@NonNull Parcel p) {
return p.readInt();
}
/** Gets the id for the field. */
public static int getFieldId(int header) {
return header & 0x0000ffff;
}
/** Reads the size. */
public static int readSize(@NonNull Parcel p, int header) {
if ((header & 0xffff0000) != 0xffff0000) {
return (header >> 16) & 0x0000ffff;
} else {
return p.readInt();
}
}
/** Skips the unknown field. */
public static void skipUnknownField(@NonNull Parcel p, int header) {
int size = readSize(p, header);
p.setDataPosition(p.dataPosition() + size);
}
private static void readAndEnforceSize(@NonNull Parcel p, int header, int required) {
final int size = readSize(p, header);
if (size != required) {
throw new ParseException(
"Expected size "
+ required
+ " got "
+ size
+ " (0x"
+ Integer.toHexString(size)
+ ")",
p);
}
}
private static void enforceSize(@NonNull Parcel p, int header, int size, int required) {
if (size != required) {
throw new ParseException(
"Expected size "
+ required
+ " got "
+ size
+ " (0x"
+ Integer.toHexString(size)
+ ")",
p);
}
}
/** Returns the end position of the object in the parcel. */
public static int validateObjectHeader(@NonNull Parcel p) {
final int header = readHeader(p);
final int size = readSize(p, header);
final int start = p.dataPosition();
if (getFieldId(header) != SafeParcelWriter.OBJECT_HEADER) {
throw new ParseException(
"Expected object header. Got 0x" + Integer.toHexString(header), p);
}
final int end = start + size;
if (end < start || end > p.dataSize()) {
throw new ParseException("Size read is invalid start=" + start + " end=" + end, p);
}
return end;
}
/** Reads a boolean. */
public static boolean readBoolean(@NonNull Parcel p, int header) {
readAndEnforceSize(p, header, 4);
return p.readInt() != 0;
}
/** Reads a {@link Boolean} object. */
@Nullable
public static Boolean readBooleanObject(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
if (size == 0) {
return null;
} else {
enforceSize(p, header, size, 4);
return p.readInt() != 0;
}
}
/** Reads a byte. */
public static byte readByte(@NonNull Parcel p, int header) {
readAndEnforceSize(p, header, 4);
return (byte) p.readInt();
}
/** Reads a char. */
public static char readChar(@NonNull Parcel p, int header) {
readAndEnforceSize(p, header, 4);
return (char) p.readInt();
}
/** Reads a short. */
public static short readShort(@NonNull Parcel p, int header) {
readAndEnforceSize(p, header, 4);
return (short) p.readInt();
}
/** Reads an int. */
public static int readInt(@NonNull Parcel p, int header) {
readAndEnforceSize(p, header, 4);
return p.readInt();
}
/** Reads an {@link Integer} object. */
@Nullable
public static Integer readIntegerObject(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
if (size == 0) {
return null;
} else {
enforceSize(p, header, size, 4);
return p.readInt();
}
}
/** Reads a long. */
public static long readLong(@NonNull Parcel p, int header) {
readAndEnforceSize(p, header, 8);
return p.readLong();
}
/** Reads a {@link Long} object. */
@Nullable
public static Long readLongObject(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
if (size == 0) {
return null;
} else {
enforceSize(p, header, size, 8);
return p.readLong();
}
}
/** Creates a {@link BigInteger}. */
@Nullable
public static BigInteger createBigInteger(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final byte[] val = p.createByteArray();
p.setDataPosition(pos + size);
return new BigInteger(val);
}
/** Reads a float. */
public static float readFloat(@NonNull Parcel p, int header) {
readAndEnforceSize(p, header, 4);
return p.readFloat();
}
/** Reads a {@link Float}. */
@Nullable
public static Float readFloatObject(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
if (size == 0) {
return null;
} else {
enforceSize(p, header, size, 4);
return p.readFloat();
}
}
/** Reads a double. */
public static double readDouble(@NonNull Parcel p, int header) {
readAndEnforceSize(p, header, 8);
return p.readDouble();
}
/** Reads a {@link Double}. */
@Nullable
public static Double readDoubleObject(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
if (size == 0) {
return null;
} else {
enforceSize(p, header, size, 8);
return p.readDouble();
}
}
/** Creates a {@link BigDecimal}. */
@Nullable
public static BigDecimal createBigDecimal(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final byte[] unscaledValue = p.createByteArray();
final int scale = p.readInt();
p.setDataPosition(pos + size);
return new BigDecimal(new BigInteger(unscaledValue), scale);
}
/** Creates a {@link String}. */
@Nullable
public static String createString(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final String result = p.readString();
p.setDataPosition(pos + size);
return result;
}
/** Reads an {@link IBinder}. */
@Nullable
public static IBinder readIBinder(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final IBinder result = p.readStrongBinder();
p.setDataPosition(pos + size);
return result;
}
/** Reads a {@link PendingIntent}. */
@Nullable
public static PendingIntent readPendingIntent(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final PendingIntent result = PendingIntent.readPendingIntentOrNullFromParcel(p);
p.setDataPosition(pos + size);
return result;
}
/** Creates a {@link Parcelable}. */
@Nullable
public static <T extends Parcelable> T createParcelable(
@NonNull Parcel p, int header, @NonNull Parcelable.Creator<T> creator) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final T result = creator.createFromParcel(p);
p.setDataPosition(pos + size);
return result;
}
/** Creates a {@link Bundle}. */
@Nullable
public static Bundle createBundle(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final Bundle result = p.readBundle();
p.setDataPosition(pos + size);
return result;
}
/** Creates a byte array. */
@Nullable
public static byte[] createByteArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final byte[] result = p.createByteArray();
p.setDataPosition(pos + size);
return result;
}
/** Creates a byte array array. */
@Nullable
public static byte[][] createByteArrayArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final int length = p.readInt();
final byte[][] result = new byte[length][];
for (int i = 0; i < length; i++) {
result[i] = p.createByteArray();
}
p.setDataPosition(pos + size);
return result;
}
/** Creates a boolean array array. */
@Nullable
public static boolean[] createBooleanArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final boolean[] result = p.createBooleanArray();
p.setDataPosition(pos + size);
return result;
}
/** Creates a char array. */
@Nullable
public static char[] createCharArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final char[] result = p.createCharArray();
p.setDataPosition(pos + size);
return result;
}
/** Creates an int array. */
@Nullable
public static int[] createIntArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final int[] result = p.createIntArray();
p.setDataPosition(pos + size);
return result;
}
/** Creates a long array. */
@Nullable
public static long[] createLongArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final long[] result = p.createLongArray();
p.setDataPosition(pos + size);
return result;
}
/** Creates a {@link BigInteger} array. */
@Nullable
public static BigInteger[] createBigIntegerArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final int length = p.readInt();
final BigInteger[] result = new BigInteger[length];
for (int i = 0; i < length; i++) {
result[i] = new BigInteger(p.createByteArray());
}
p.setDataPosition(pos + size);
return result;
}
/** Creates a float array. */
@Nullable
public static float[] createFloatArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final float[] result = p.createFloatArray();
p.setDataPosition(pos + size);
return result;
}
/** Creates a double array. */
@Nullable
public static double[] createDoubleArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final double[] result = p.createDoubleArray();
p.setDataPosition(pos + size);
return result;
}
/** Creates a {@link BigDecimal} array. */
@Nullable
public static BigDecimal[] createBigDecimalArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final int length = p.readInt();
final BigDecimal[] result = new BigDecimal[length];
for (int i = 0; i < length; i++) {
byte[] unscaledValue = p.createByteArray();
int scale = p.readInt();
result[i] = new BigDecimal(new BigInteger(unscaledValue), scale);
}
p.setDataPosition(pos + size);
return result;
}
/** Creates a {@link String} array. */
@Nullable
public static String[] createStringArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final String[] result = p.createStringArray();
p.setDataPosition(pos + size);
return result;
}
/** Creates a {@link IBinder} array. */
@Nullable
public static IBinder[] createIBinderArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final IBinder[] result = p.createBinderArray();
p.setDataPosition(pos + size);
return result;
}
/** Creates a {@link Boolean} list. */
@Nullable
public static ArrayList<Boolean> createBooleanList(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final ArrayList<Boolean> result = new ArrayList<Boolean>();
final int count = p.readInt();
for (int i = 0; i < count; i++) {
result.add(p.readInt() != 0 ? true : false);
}
p.setDataPosition(pos + size);
return result;
}
/** Creates a {@link Integer} list. */
@Nullable
public static ArrayList<Integer> createIntegerList(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final ArrayList<Integer> result = new ArrayList<Integer>();
final int count = p.readInt();
for (int i = 0; i < count; i++) {
result.add(p.readInt());
}
p.setDataPosition(pos + size);
return result;
}
/** Creates a {@link SparseBooleanArray}. */
@Nullable
public static SparseBooleanArray createSparseBooleanArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
SparseBooleanArray result = p.readSparseBooleanArray();
p.setDataPosition(pos + size);
return result;
}
/** Creates a {@link SparseIntArray}. */
@Nullable
public static SparseIntArray createSparseIntArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final SparseIntArray result = new SparseIntArray();
final int count = p.readInt();
for (int i = 0; i < count; i++) {
int key = p.readInt();
int value = p.readInt();
result.append(key, value);
}
p.setDataPosition(pos + size);
return result;
}
/** Creates a {@link Float} {@link SparseArray}. */
@Nullable
public static SparseArray<Float> createFloatSparseArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final SparseArray<Float> result = new SparseArray<Float>();
final int count = p.readInt();
for (int i = 0; i < count; i++) {
int key = p.readInt();
float value = p.readFloat();
result.append(key, value);
}
p.setDataPosition(pos + size);
return result;
}
/** Creates a {@link Double} {@link SparseArray}. */
@Nullable
public static SparseArray<Double> createDoubleSparseArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final SparseArray<Double> result = new SparseArray<Double>();
final int count = p.readInt();
for (int i = 0; i < count; i++) {
int key = p.readInt();
double value = p.readDouble();
result.append(key, value);
}
p.setDataPosition(pos + size);
return result;
}
/** Creates a {@link SparseLongArray}. */
@Nullable
public static SparseLongArray createSparseLongArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final SparseLongArray result = new SparseLongArray();
final int count = p.readInt();
for (int i = 0; i < count; i++) {
int key = p.readInt();
long value = p.readLong();
result.append(key, value);
}
p.setDataPosition(pos + size);
return result;
}
/** Creates a {@link String} {@link SparseArray}. */
@Nullable
public static SparseArray<String> createStringSparseArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final SparseArray<String> result = new SparseArray<String>();
final int count = p.readInt();
for (int i = 0; i < count; i++) {
int key = p.readInt();
String value = p.readString();
result.append(key, value);
}
p.setDataPosition(pos + size);
return result;
}
/** Creates a {@link Parcel} {@link SparseArray}. */
@Nullable
public static SparseArray<Parcel> createParcelSparseArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final int count = p.readInt();
final SparseArray<Parcel> result = new SparseArray<Parcel>();
for (int i = 0; i < count; i++) {
int key = p.readInt();
// read in the flag of whether this element is null
int parcelSize = p.readInt();
if (parcelSize != 0) {
// non-null
int currentDataPosition = p.dataPosition();
Parcel item = Parcel.obtain();
item.appendFrom(p, currentDataPosition, parcelSize);
result.append(key, item);
// move p's data position
p.setDataPosition(currentDataPosition + parcelSize);
} else {
// is null
result.append(key, null);
}
}
p.setDataPosition(pos + size);
return result;
}
/** Creates typed {@link SparseArray}. */
@Nullable
public static <T> SparseArray<T> createTypedSparseArray(
@NonNull Parcel p, int header, @NonNull Parcelable.Creator<T> c) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final int count = p.readInt();
final SparseArray<T> result = new SparseArray<>();
for (int i = 0; i < count; i++) {
int key = p.readInt();
T value;
if (p.readInt() != 0) {
value = c.createFromParcel(p);
} else {
value = null;
}
result.append(key, value);
}
p.setDataPosition(pos + size);
return result;
}
/** Creates {@link IBinder} {@link SparseArray}. */
@Nullable
public static SparseArray<IBinder> createIBinderSparseArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final int count = p.readInt();
final SparseArray<IBinder> result = new SparseArray<>(count);
for (int i = 0; i < count; i++) {
int key = p.readInt();
IBinder value = p.readStrongBinder();
result.append(key, value);
}
p.setDataPosition(pos + size);
return result;
}
/** Creates byte array {@link SparseArray}. */
@Nullable
public static SparseArray<byte[]> createByteArraySparseArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final int count = p.readInt();
final SparseArray<byte[]> result = new SparseArray<byte[]>(count);
for (int i = 0; i < count; i++) {
int key = p.readInt();
byte[] value = p.createByteArray();
result.append(key, value);
}
p.setDataPosition(pos + size);
return result;
}
/** Creates {@link Long} {@link ArrayList}. */
@Nullable
public static ArrayList<Long> createLongList(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final ArrayList<Long> result = new ArrayList<Long>();
final int count = p.readInt();
for (int i = 0; i < count; i++) {
result.add(p.readLong());
}
p.setDataPosition(pos + size);
return result;
}
/** Creates {@link Float} {@link ArrayList}. */
@Nullable
public static ArrayList<Float> createFloatList(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final ArrayList<Float> result = new ArrayList<Float>();
final int count = p.readInt();
for (int i = 0; i < count; i++) {
result.add(p.readFloat());
}
p.setDataPosition(pos + size);
return result;
}
/** Creates {@link Double} {@link ArrayList}. */
@Nullable
public static ArrayList<Double> createDoubleList(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final ArrayList<Double> result = new ArrayList<Double>();
final int count = p.readInt();
for (int i = 0; i < count; i++) {
result.add(p.readDouble());
}
p.setDataPosition(pos + size);
return result;
}
/** Creates {@link String} {@link ArrayList}. */
@Nullable
public static ArrayList<String> createStringList(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final ArrayList<String> result = p.createStringArrayList();
p.setDataPosition(pos + size);
return result;
}
/** Creates {@link IBinder} {@link ArrayList}. */
@Nullable
public static ArrayList<IBinder> createIBinderList(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final ArrayList<IBinder> result = p.createBinderArrayList();
p.setDataPosition(pos + size);
return result;
}
/** Creates typed array. */
@Nullable
public static <T> T[] createTypedArray(
@NonNull Parcel p, int header, @NonNull Parcelable.Creator<T> c) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final T[] result = p.createTypedArray(c);
p.setDataPosition(pos + size);
return result;
}
/** Creates typed {@link ArrayList}. */
@Nullable
public static <T> ArrayList<T> createTypedList(
@NonNull Parcel p, int header, @NonNull Parcelable.Creator<T> c) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final ArrayList<T> result = p.createTypedArrayList(c);
p.setDataPosition(pos + size);
return result;
}
/** Creates {@link Parcel}. */
@Nullable
public static Parcel createParcel(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final Parcel result = Parcel.obtain();
result.appendFrom(p, pos, size);
p.setDataPosition(pos + size);
return result;
}
/** Creates {@link Parcel} array. */
@Nullable
public static Parcel[] createParcelArray(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final int length = p.readInt();
final Parcel[] result = new Parcel[length];
for (int i = 0; i < length; i++) {
int parcelSize = p.readInt();
if (parcelSize != 0) {
int currentDataPosition = p.dataPosition();
Parcel item = Parcel.obtain();
item.appendFrom(p, currentDataPosition, parcelSize);
result[i] = item;
// move p's data position
p.setDataPosition(currentDataPosition + parcelSize);
} else {
result[i] = null;
}
}
p.setDataPosition(pos + size);
return result;
}
/** Creates {@link Parcel} {@link ArrayList}. */
@Nullable
public static ArrayList<Parcel> createParcelList(@NonNull Parcel p, int header) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return null;
}
final int length = p.readInt();
final ArrayList<Parcel> result = new ArrayList<Parcel>();
for (int i = 0; i < length; i++) {
// read in the flag of whether this element is null
int parcelSize = p.readInt();
if (parcelSize != 0) {
// non-null
int currentDataPosition = p.dataPosition();
Parcel item = Parcel.obtain();
item.appendFrom(p, currentDataPosition, parcelSize);
result.add(item);
// move p's data position
p.setDataPosition(currentDataPosition + parcelSize);
} else {
// is null
result.add(null);
}
}
p.setDataPosition(pos + size);
return result;
}
/** Reads the list. */
public static void readList(
@NonNull Parcel p,
int header,
@SuppressWarnings("rawtypes") @NonNull List list,
@Nullable ClassLoader loader) {
final int size = readSize(p, header);
final int pos = p.dataPosition();
if (size == 0) {
return;
}
p.readList(list, loader);
p.setDataPosition(pos + size);
}
/** Ensures at end. */
public static void ensureAtEnd(@NonNull Parcel parcel, int end) {
if (parcel.dataPosition() != end) {
throw new ParseException("Overread allowed size end=" + end, parcel);
}
}
}