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

Commit c48eeadf authored by Hao Ke's avatar Hao Ke Committed by Automerger Merge Worker
Browse files

Merge "Adding typed Parcel read APIs for Serializable." am: bce40e7c am:...

Merge "Adding typed Parcel read APIs for Serializable." am: bce40e7c am: 9a614513 am: ff54e814 am: 1c9ca7b8

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1870153

Change-Id: I33d3078eacec37b33708d6b8c74637f410178435
parents 9843ab96 1c9ca7b8
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -31534,6 +31534,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);
+64 −19
Original line number Original line Diff line number Diff line
@@ -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
    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
    @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();
        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;
        }
        }


        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();
            byte[] serializedData = createByteArray();
            ByteArrayInputStream bais = new ByteArrayInputStream(serializedData);
            ByteArrayInputStream bais = new ByteArrayInputStream(serializedData);
        try {
            ObjectInputStream ois = new ObjectInputStream(bais) {
            ObjectInputStream ois = new ObjectInputStream(bais) {
                @Override
                @Override
                protected Class<?> resolveClass(ObjectStreamClass osClass)
                protected Class<?> resolveClass(ObjectStreamClass osClass)
@@ -4168,21 +4204,30 @@ 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);
        }
        }
    }
    }