Merge "Adding typed Parcel read APIs for Serializable."
This commit is contained in:
@@ -31473,6 +31473,7 @@ package android.os {
|
|||||||
method @Nullable public android.os.PersistableBundle readPersistableBundle();
|
method @Nullable public android.os.PersistableBundle readPersistableBundle();
|
||||||
method @Nullable public android.os.PersistableBundle readPersistableBundle(@Nullable ClassLoader);
|
method @Nullable public android.os.PersistableBundle readPersistableBundle(@Nullable ClassLoader);
|
||||||
method @Nullable public java.io.Serializable readSerializable();
|
method @Nullable public java.io.Serializable readSerializable();
|
||||||
|
method @Nullable public <T extends java.io.Serializable> T readSerializable(@Nullable ClassLoader, @NonNull Class<T>);
|
||||||
method @NonNull public android.util.Size readSize();
|
method @NonNull public android.util.Size readSize();
|
||||||
method @NonNull public android.util.SizeF readSizeF();
|
method @NonNull public android.util.SizeF readSizeF();
|
||||||
method @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader);
|
method @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader);
|
||||||
|
|||||||
@@ -2448,9 +2448,9 @@ public final class Parcel {
|
|||||||
|
|
||||||
writeByteArray(baos.toByteArray());
|
writeByteArray(baos.toByteArray());
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
throw new RuntimeException("Parcelable encountered " +
|
throw new BadParcelableException("Parcelable encountered "
|
||||||
"IOException writing serializable object (name = " + name +
|
+ "IOException writing serializable object (name = "
|
||||||
")", ioe);
|
+ name + ")", ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3818,7 +3818,7 @@ public final class Parcel {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VAL_SERIALIZABLE:
|
case VAL_SERIALIZABLE:
|
||||||
object = readSerializable(loader);
|
object = readSerializableInternal(loader, clazz);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VAL_PARCELABLEARRAY:
|
case VAL_PARCELABLEARRAY:
|
||||||
@@ -4144,12 +4144,37 @@ public final class Parcel {
|
|||||||
* wasn't found in the parcel.
|
* wasn't found in the parcel.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public final Serializable readSerializable() {
|
public Serializable readSerializable() {
|
||||||
return readSerializable(null);
|
return readSerializableInternal(/* loader */ null, /* clazz */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as {@link #readSerializable()} but accepts {@code loader} parameter
|
||||||
|
* as the primary classLoader for resolving the Serializable class; and {@code clazz} parameter
|
||||||
|
* as the required type.
|
||||||
|
*
|
||||||
|
* @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
|
||||||
|
* is not an instance of that class or any of its children class or there there was an error
|
||||||
|
* deserializing the object.
|
||||||
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
private final Serializable readSerializable(@Nullable final ClassLoader loader) {
|
public <T extends Serializable> T readSerializable(@Nullable ClassLoader loader,
|
||||||
|
@NonNull Class<T> clazz) {
|
||||||
|
Objects.requireNonNull(clazz);
|
||||||
|
return readSerializableInternal(loader, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param clazz The type of the serializable expected or {@code null} for performing no checks
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private <T> T readSerializableInternal(@Nullable final ClassLoader loader,
|
||||||
|
@Nullable Class<T> clazz) {
|
||||||
|
if (clazz != null && !Serializable.class.isAssignableFrom(clazz)) {
|
||||||
|
throw new BadParcelableException("About to unparcel a serializable object "
|
||||||
|
+ " but class required " + clazz.getName() + " is not Serializable");
|
||||||
|
}
|
||||||
|
|
||||||
String name = readString();
|
String name = readString();
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
// For some reason we were unable to read the name of the Serializable (either there
|
// For some reason we were unable to read the name of the Serializable (either there
|
||||||
@@ -4158,9 +4183,20 @@ public final class Parcel {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] serializedData = createByteArray();
|
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(serializedData);
|
|
||||||
try {
|
try {
|
||||||
|
if (clazz != null && loader != null) {
|
||||||
|
// If custom classloader is provided, resolve the type of serializable using the
|
||||||
|
// name, then check the type before deserialization. As in this case we can resolve
|
||||||
|
// the class the same way as ObjectInputStream, using the provided classloader.
|
||||||
|
Class<?> cl = Class.forName(name, false, loader);
|
||||||
|
if (!clazz.isAssignableFrom(cl)) {
|
||||||
|
throw new BadParcelableException("Serializable object "
|
||||||
|
+ cl.getName() + " is not a subclass of required class "
|
||||||
|
+ clazz.getName() + " provided in the parameter");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
byte[] serializedData = createByteArray();
|
||||||
|
ByteArrayInputStream bais = new ByteArrayInputStream(serializedData);
|
||||||
ObjectInputStream ois = new ObjectInputStream(bais) {
|
ObjectInputStream ois = new ObjectInputStream(bais) {
|
||||||
@Override
|
@Override
|
||||||
protected Class<?> resolveClass(ObjectStreamClass osClass)
|
protected Class<?> resolveClass(ObjectStreamClass osClass)
|
||||||
@@ -4168,22 +4204,31 @@ public final class Parcel {
|
|||||||
// try the custom classloader if provided
|
// try the custom classloader if provided
|
||||||
if (loader != null) {
|
if (loader != null) {
|
||||||
Class<?> c = Class.forName(osClass.getName(), false, loader);
|
Class<?> c = Class.forName(osClass.getName(), false, loader);
|
||||||
if (c != null) {
|
return Objects.requireNonNull(c);
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return super.resolveClass(osClass);
|
return super.resolveClass(osClass);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (Serializable) ois.readObject();
|
T object = (T) ois.readObject();
|
||||||
|
if (clazz != null && loader == null) {
|
||||||
|
// If custom classloader is not provided, check the type of the serializable using
|
||||||
|
// the deserialized object, as we cannot resolve the class the same way as
|
||||||
|
// ObjectInputStream.
|
||||||
|
if (!clazz.isAssignableFrom(object.getClass())) {
|
||||||
|
throw new BadParcelableException("Serializable object "
|
||||||
|
+ object.getClass().getName() + " is not a subclass of required class "
|
||||||
|
+ clazz.getName() + " provided in the parameter");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return object;
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
throw new RuntimeException("Parcelable encountered " +
|
throw new BadParcelableException("Parcelable encountered "
|
||||||
"IOException reading a Serializable object (name = " + name +
|
+ "IOException reading a Serializable object (name = "
|
||||||
")", ioe);
|
+ name + ")", ioe);
|
||||||
} catch (ClassNotFoundException cnfe) {
|
} catch (ClassNotFoundException cnfe) {
|
||||||
throw new RuntimeException("Parcelable encountered " +
|
throw new BadParcelableException("Parcelable encountered "
|
||||||
"ClassNotFoundException reading a Serializable object (name = "
|
+ "ClassNotFoundException reading a Serializable object (name = "
|
||||||
+ name + ")", cnfe);
|
+ name + ")", cnfe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user