diff options
| -rw-r--r-- | core/java/android/content/pm/PackageCleanItem.java | 2 | ||||
| -rw-r--r-- | core/java/android/content/pm/ParceledListSlice.java | 3 | ||||
| -rw-r--r-- | core/java/android/os/Parcel.java | 90 | ||||
| -rw-r--r-- | core/java/android/os/Parcelable.java | 5 |
4 files changed, 58 insertions, 42 deletions
diff --git a/core/java/android/content/pm/PackageCleanItem.java b/core/java/android/content/pm/PackageCleanItem.java index b1896aaa365e..e1656d6f192d 100644 --- a/core/java/android/content/pm/PackageCleanItem.java +++ b/core/java/android/content/pm/PackageCleanItem.java @@ -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; diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java index 335a45e40777..e5c2203a2d20 100644 --- a/core/java/android/content/pm/ParceledListSlice.java +++ b/core/java/android/content/pm/ParceledListSlice.java @@ -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; diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 9d8a1bafb93e..ff91cc8c2d22 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -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; @@ -1373,8 +1374,7 @@ public final class Parcel { writeString(null); return; } - String name = p.getClass().getName(); - writeString(name); + writeParcelableCreator(p); p.writeToParcel(this, parcelableFlags); } @@ -2275,78 +2275,94 @@ 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); + + "Parcelable.Creator object called " + + "CREATOR on class " + name); } if (creator == null) { throw new BadParcelableException("Parcelable protocol requires a " - + "Parcelable.Creator object called " - + " CREATOR on class " + name); + + "non-null Parcelable.Creator object called " + + "CREATOR on class " + name); } map.put(name, creator); @@ -2369,7 +2385,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; } @@ -2424,8 +2440,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) { diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java index 594fbb2c46e5..448b591718f8 100644 --- a/core/java/android/os/Parcelable.java +++ b/core/java/android/os/Parcelable.java @@ -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> * |