Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bce40e7c authored by Hao Ke's avatar Hao Ke Committed by Gerrit Code Review
Browse files

Merge "Adding typed Parcel read APIs for Serializable."

parents 839597de ec4b60c1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -31473,6 +31473,7 @@ package android.os {
    method @Nullable public android.os.PersistableBundle readPersistableBundle();
    method @Nullable public android.os.PersistableBundle readPersistableBundle(@Nullable ClassLoader);
    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.SizeF readSizeF();
    method @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader);
+64 −19
Original line number Diff line number Diff line
@@ -2448,9 +2448,9 @@ public final class Parcel {

            writeByteArray(baos.toByteArray());
        } catch (IOException ioe) {
            throw new RuntimeException("Parcelable encountered " +
                "IOException writing serializable object (name = " + name +
                ")", ioe);
            throw new BadParcelableException("Parcelable encountered "
                    + "IOException writing serializable object (name = "
                    + name + ")", ioe);
        }
    }

@@ -3818,7 +3818,7 @@ public final class Parcel {
                break;

            case VAL_SERIALIZABLE:
                object = readSerializable(loader);
                object = readSerializableInternal(loader, clazz);
                break;

            case VAL_PARCELABLEARRAY:
@@ -4144,12 +4144,37 @@ public final class Parcel {
     * wasn't found in the parcel.
     */
    @Nullable
    public final Serializable readSerializable() {
        return readSerializable(null);
    public Serializable readSerializable() {
        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
    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 final Serializable readSerializable(@Nullable final ClassLoader loader) {
    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();
        if (name == null) {
            // 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;
        }

        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);
        try {
            ObjectInputStream ois = new ObjectInputStream(bais) {
                @Override
                protected Class<?> resolveClass(ObjectStreamClass osClass)
@@ -4168,21 +4204,30 @@ public final class Parcel {
                    // try the custom classloader if provided
                    if (loader != null) {
                        Class<?> c = Class.forName(osClass.getName(), false, loader);
                        if (c != null) {
                            return c;
                        }
                        return Objects.requireNonNull(c);
                    }
                    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) {
            throw new RuntimeException("Parcelable encountered " +
                "IOException reading a Serializable object (name = " + name +
                ")", ioe);
            throw new BadParcelableException("Parcelable encountered "
                    + "IOException reading a Serializable object (name = "
                    + name + ")", ioe);
        } catch (ClassNotFoundException cnfe) {
            throw new RuntimeException("Parcelable encountered " +
                "ClassNotFoundException reading a Serializable object (name = "
            throw new BadParcelableException("Parcelable encountered "
                    + "ClassNotFoundException reading a Serializable object (name = "
                    + name + ")", cnfe);
        }
    }