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

Commit 52dbaa08 authored by Neil Fuller's avatar Neil Fuller Committed by Android (Google) Code Review
Browse files

Merge "Add checks for types in Parcel / avoid class initialization"

parents 0f70ca0e 44e440cc
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ import android.os.Parcel;
import android.os.Parcelable;

/** @hide */
public class PackageCleanItem {
public class PackageCleanItem implements Parcelable {
    public final int userId;
    public final String packageName;
    public final boolean andCode;
+2 −1
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ public class ParceledListSlice<T extends Parcelable> implements Parcelable {
        mList = list;
    }

    @SuppressWarnings("unchecked")
    private ParceledListSlice(Parcel p, ClassLoader loader) {
        final int N = p.readInt();
        mList = new ArrayList<T>(N);
@@ -63,7 +64,7 @@ public class ParceledListSlice<T extends Parcelable> implements Parcelable {
            return;
        }

        Parcelable.Creator<T> creator = p.readParcelableCreator(loader);
        Parcelable.Creator<?> creator = p.readParcelableCreator(loader);
        Class<?> listElementClass = null;

        int i = 0;
+53 −37
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -1375,8 +1376,7 @@ public final class Parcel {
            writeString(null);
            return;
        }
        String name = p.getClass().getName();
        writeString(name);
        writeParcelableCreator(p);
        p.writeToParcel(this, parcelableFlags);
    }

@@ -2277,77 +2277,93 @@ public final class Parcel {
     * @throws BadParcelableException Throws BadParcelableException if there
     * was an error trying to instantiate the Parcelable.
     */
    @SuppressWarnings("unchecked")
    public final <T extends Parcelable> T readParcelable(ClassLoader loader) {
        Parcelable.Creator<T> creator = readParcelableCreator(loader);
        Parcelable.Creator<?> creator = readParcelableCreator(loader);
        if (creator == null) {
            return null;
        }
        if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
            return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader);
          Parcelable.ClassLoaderCreator<?> classLoaderCreator =
              (Parcelable.ClassLoaderCreator<?>) creator;
          return (T) classLoaderCreator.createFromParcel(this, loader);
        }
        return creator.createFromParcel(this);
        return (T) creator.createFromParcel(this);
    }

    /** @hide */
    public final <T extends Parcelable> T readCreator(Parcelable.Creator<T> creator,
    @SuppressWarnings("unchecked")
    public final <T extends Parcelable> T readCreator(Parcelable.Creator<?> creator,
            ClassLoader loader) {
        if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
            return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader);
          Parcelable.ClassLoaderCreator<?> classLoaderCreator =
              (Parcelable.ClassLoaderCreator<?>) creator;
          return (T) classLoaderCreator.createFromParcel(this, loader);
        }
        return creator.createFromParcel(this);
        return (T) creator.createFromParcel(this);
    }

    /** @hide */
    public final <T extends Parcelable> Parcelable.Creator<T> readParcelableCreator(
            ClassLoader loader) {
    public final Parcelable.Creator<?> readParcelableCreator(ClassLoader loader) {
        String name = readString();
        if (name == null) {
            return null;
        }
        Parcelable.Creator<T> creator;
        Parcelable.Creator<?> creator;
        synchronized (mCreators) {
            HashMap<String,Parcelable.Creator> map = mCreators.get(loader);
            HashMap<String,Parcelable.Creator<?>> map = mCreators.get(loader);
            if (map == null) {
                map = new HashMap<String,Parcelable.Creator>();
                map = new HashMap<>();
                mCreators.put(loader, map);
            }
            creator = map.get(name);
            if (creator == null) {
                try {
                    Class c = loader == null ?
                        Class.forName(name) : Class.forName(name, true, loader);
                    Field f = c.getField("CREATOR");
                    creator = (Parcelable.Creator)f.get(null);
                    // If loader == null, explicitly emulate Class.forName(String) "caller
                    // classloader" behavior.
                    ClassLoader parcelableClassLoader =
                            (loader == null ? getClass().getClassLoader() : loader);
                    // Avoid initializing the Parcelable class until we know it implements
                    // Parcelable and has the necessary CREATOR field. http://b/1171613.
                    Class<?> parcelableClass = Class.forName(name, false /* initialize */,
                            parcelableClassLoader);
                    if (!Parcelable.class.isAssignableFrom(parcelableClass)) {
                        throw new BadParcelableException("Parcelable protocol requires that the "
                                + "class implements Parcelable");
                    }
                    Field f = parcelableClass.getField("CREATOR");
                    if ((f.getModifiers() & Modifier.STATIC) == 0) {
                        throw new BadParcelableException("Parcelable protocol requires "
                                + "the CREATOR object to be static on class " + name);
                    }
                    Class<?> creatorType = f.getType();
                    if (!Parcelable.Creator.class.isAssignableFrom(creatorType)) {
                        // Fail before calling Field.get(), not after, to avoid initializing
                        // parcelableClass unnecessarily.
                        throw new BadParcelableException("Parcelable protocol requires a "
                                + "Parcelable.Creator object called "
                                + "CREATOR on class " + name);
                    }
                    creator = (Parcelable.Creator<?>) f.get(null);
                }
                catch (IllegalAccessException e) {
                    Log.e(TAG, "Illegal access when unmarshalling: "
                                        + name, e);
                    Log.e(TAG, "Illegal access when unmarshalling: " + name, e);
                    throw new BadParcelableException(
                            "IllegalAccessException when unmarshalling: " + name);
                }
                catch (ClassNotFoundException e) {
                    Log.e(TAG, "Class not found when unmarshalling: "
                                        + name, e);
                    Log.e(TAG, "Class not found when unmarshalling: " + name, e);
                    throw new BadParcelableException(
                            "ClassNotFoundException when unmarshalling: " + name);
                }
                catch (ClassCastException e) {
                    throw new BadParcelableException("Parcelable protocol requires a "
                                        + "Parcelable.Creator object called "
                                        + " CREATOR on class " + name);
                }
                catch (NoSuchFieldException e) {
                    throw new BadParcelableException("Parcelable protocol requires a "
                            + "Parcelable.Creator object called "
                            + "CREATOR on class " + name);
                }
                catch (NullPointerException e) {
                    throw new BadParcelableException("Parcelable protocol requires "
                            + "the CREATOR object to be static on class " + name);
                }
                if (creator == null) {
                    throw new BadParcelableException("Parcelable protocol requires a "
                                        + "Parcelable.Creator object called "
                            + "non-null Parcelable.Creator object called "
                            + "CREATOR on class " + name);
                }

@@ -2371,7 +2387,7 @@ public final class Parcel {
        }
        Parcelable[] p = new Parcelable[N];
        for (int i = 0; i < N; i++) {
            p[i] = (Parcelable) readParcelable(loader);
            p[i] = readParcelable(loader);
        }
        return p;
    }
@@ -2426,8 +2442,8 @@ public final class Parcel {
    // Cache of previously looked up CREATOR.createFromParcel() methods for
    // particular classes.  Keys are the names of the classes, values are
    // Method objects.
    private static final HashMap<ClassLoader,HashMap<String,Parcelable.Creator>>
        mCreators = new HashMap<ClassLoader,HashMap<String,Parcelable.Creator>>();
    private static final HashMap<ClassLoader,HashMap<String,Parcelable.Creator<?>>>
        mCreators = new HashMap<>();

    /** @hide for internal use only. */
    static protected final Parcel obtain(int obj) {
+2 −3
Original line number Diff line number Diff line
@@ -19,9 +19,8 @@ package android.os;
/**
 * Interface for classes whose instances can be written to
 * and restored from a {@link Parcel}.  Classes implementing the Parcelable
 * interface must also have a static field called <code>CREATOR</code>, which
 * is an object implementing the {@link Parcelable.Creator Parcelable.Creator}
 * interface.
 * interface must also have a non-null static field called <code>CREATOR</code>
 * of a type that implements the {@link Parcelable.Creator} interface.
 * 
 * <p>A typical implementation of Parcelable is:</p>
 *