diff --git a/src/org/microg/safeparcel/SafeParcelReader.java b/src/org/microg/safeparcel/SafeParcelReader.java index 80d9576..4bc26db 100644 --- a/src/org/microg/safeparcel/SafeParcelReader.java +++ b/src/org/microg/safeparcel/SafeParcelReader.java @@ -20,112 +20,125 @@ import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; +import java.util.ArrayList; +import java.util.List; + public class SafeParcelReader { - public static int halfOf(int i) { - return i & 0xFFFF; - } + public static int halfOf(int i) { + return i & 0xFFFF; + } - public static int readSingleInt(Parcel parcel) { - return parcel.readInt(); - } + public static int readSingleInt(Parcel parcel) { + return parcel.readInt(); + } - private static int readStart(Parcel parcel, int first) { - if ((first & 0xFFFF0000) != -65536) - return first >> 16 & 0xFFFF; - return parcel.readInt(); - } + private static int readStart(Parcel parcel, int first) { + if ((first & 0xFFFF0000) != -65536) + return first >> 16 & 0xFFFF; + return parcel.readInt(); + } - private static void readStart(Parcel parcel, int position, int length) { - int i = readStart(parcel, position); - if (i != length) - throw new ReadException("Expected size " + length + " got " + i + " (0x" + Integer.toHexString(i) + ")", parcel); - } + private static void readStart(Parcel parcel, int position, int length) { + int i = readStart(parcel, position); + if (i != length) + throw new ReadException("Expected size " + length + " got " + i + " (0x" + Integer.toHexString(i) + ")", parcel); + } - public static int readStart(Parcel parcel) { - int first = readSingleInt(parcel); - int length = readStart(parcel, first); - int start = parcel.dataPosition(); - if (halfOf(first) != SafeParcelable.SAFE_PARCEL_MAGIC) - throw new ReadException("Expected object header. Got 0x" + Integer.toHexString(first), parcel); - int end = start + length; - if ((end < start) || (end > parcel.dataSize())) - throw new ReadException("Size read is invalid start=" + start + " end=" + end, parcel); - return end; - } + public static int readStart(Parcel parcel) { + int first = readSingleInt(parcel); + int length = readStart(parcel, first); + int start = parcel.dataPosition(); + if (halfOf(first) != SafeParcelable.SAFE_PARCEL_MAGIC) + throw new ReadException("Expected object header. Got 0x" + Integer.toHexString(first), parcel); + int end = start + length; + if ((end < start) || (end > parcel.dataSize())) + throw new ReadException("Size read is invalid start=" + start + " end=" + end, parcel); + return end; + } - public static int readInt(Parcel parcel, int position) { - readStart(parcel, position, 4); - return parcel.readInt(); - } + public static int readInt(Parcel parcel, int position) { + readStart(parcel, position, 4); + return parcel.readInt(); + } - public static byte readByte(Parcel parcel, int position) { - readStart(parcel, position, 4); - return (byte) parcel.readInt(); - } + public static byte readByte(Parcel parcel, int position) { + readStart(parcel, position, 4); + return (byte) parcel.readInt(); + } - public static short readShort(Parcel parcel, int position) { - readStart(parcel, position, 4); - return (short) parcel.readInt(); - } + public static short readShort(Parcel parcel, int position) { + readStart(parcel, position, 4); + return (short) parcel.readInt(); + } - public static boolean readBool(Parcel parcel, int position) { - readStart(parcel, position, 4); - return parcel.readInt() != 0; - } + public static boolean readBool(Parcel parcel, int position) { + readStart(parcel, position, 4); + return parcel.readInt() != 0; + } - public static long readLong(Parcel parcel, int position) { - readStart(parcel, position, 8); - return parcel.readLong(); - } + public static long readLong(Parcel parcel, int position) { + readStart(parcel, position, 8); + return parcel.readLong(); + } - public static float readFloat(Parcel parcel, int position) { - readStart(parcel, position, 4); - return parcel.readFloat(); - } + public static float readFloat(Parcel parcel, int position) { + readStart(parcel, position, 4); + return parcel.readFloat(); + } - public static double readDouble(Parcel parcel, int position) { - readStart(parcel, position, 8); - return parcel.readDouble(); - } + public static double readDouble(Parcel parcel, int position) { + readStart(parcel, position, 8); + return parcel.readDouble(); + } - public static String readString(Parcel parcel, int position) { - int length = readStart(parcel, position); - int start = parcel.dataPosition(); - if (length == 0) - return null; - String string = parcel.readString(); - parcel.setDataPosition(start + length); - return string; - } + public static String readString(Parcel parcel, int position) { + int length = readStart(parcel, position); + int start = parcel.dataPosition(); + if (length == 0) + return null; + String string = parcel.readString(); + parcel.setDataPosition(start + length); + return string; + } - public static IBinder readBinder(Parcel parcel, int position) { - int length = readStart(parcel, position); - int start = parcel.dataPosition(); - if (length == 0) - return null; - IBinder binder = parcel.readStrongBinder(); - parcel.setDataPosition(start + length); - return binder; - } + public static IBinder readBinder(Parcel parcel, int position) { + int length = readStart(parcel, position); + int start = parcel.dataPosition(); + if (length == 0) + return null; + IBinder binder = parcel.readStrongBinder(); + parcel.setDataPosition(start + length); + return binder; + } - public static T readParcelable(Parcel parcel, int position, Parcelable.Creator creator) { - int length = readStart(parcel, position); - int start = parcel.dataPosition(); - if (length == 0) - return null; - T t = creator.createFromParcel(parcel); - parcel.setDataPosition(start + length); - return t; - } + public static T readParcelable(Parcel parcel, int position, Parcelable.Creator creator) { + int length = readStart(parcel, position); + int start = parcel.dataPosition(); + if (length == 0) + return null; + T t = creator.createFromParcel(parcel); + parcel.setDataPosition(start + length); + return t; + } - public static void skip(Parcel parcel, int position) { - int i = readStart(parcel, position); - parcel.setDataPosition(parcel.dataPosition() + i); - } + public static ArrayList readList(Parcel parcel, int position, ClassLoader classLoader) { + int length = readStart(parcel, position); + int start = parcel.dataPosition(); + if (length == 0) + return null; + ArrayList list = parcel.readArrayList(classLoader); + parcel.setDataPosition(start + length); + return list; + } - public static class ReadException extends RuntimeException { - public ReadException(String message, Parcel parcel) { - super(message); - } - } + public static void skip(Parcel parcel, int position) { + int i = readStart(parcel, position); + parcel.setDataPosition(parcel.dataPosition() + i); + } + + public static class ReadException extends RuntimeException { + public ReadException(String message, Parcel parcel) { + super(message); + } + } } diff --git a/src/org/microg/safeparcel/SafeParcelUtil.java b/src/org/microg/safeparcel/SafeParcelUtil.java index 18ed3aa..1b39ebe 100644 --- a/src/org/microg/safeparcel/SafeParcelUtil.java +++ b/src/org/microg/safeparcel/SafeParcelUtil.java @@ -8,7 +8,9 @@ import android.util.Log; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; public class SafeParcelUtil { @@ -104,6 +106,15 @@ public class SafeParcelUtil { } } + private static ClassLoader getClassLoader(Field field) { + try { + String type = field.getAnnotation(SafeParceled.class).subType(); + return Class.forName(type).getClassLoader(); + } catch (ClassNotFoundException e) { + return ClassLoader.getSystemClassLoader(); + } + } + private static void writeField(SafeParcelable object, Parcel parcel, Field field, int flags) throws IllegalAccessException { int num = field.getAnnotation(SafeParceled.class).value(); @@ -117,6 +128,9 @@ public class SafeParcelUtil { case Binder: SafeParcelWriter.write(parcel, num, (IBinder) field.get(object), mayNull); break; + case List: + SafeParcelWriter.write(parcel, num, (List) field.get(object), mayNull); + break; case Integer: SafeParcelWriter.write(parcel, num, (Integer) field.get(object)); break; @@ -151,6 +165,9 @@ public class SafeParcelUtil { field.set(object, SafeParcelReader.readBinder(parcel, position)); break; + case List: + field.set(object, SafeParcelReader.readList(parcel, position, getClassLoader(field))); + break; case Integer: field.set(object, SafeParcelReader.readInt(parcel, position)); break; @@ -173,13 +190,15 @@ public class SafeParcelUtil { } private enum SafeParcelType { - Parcelable, Binder, Integer, Long, Boolean, Float, Double, String; + Parcelable, Binder, Integer, Long, Boolean, Float, Double, String, List; public static SafeParcelType fromClass(Class clazz) { if (Parcelable.class.isAssignableFrom(clazz)) return Parcelable; if (IBinder.class.isAssignableFrom(clazz)) return Binder; + if (clazz == List.class || clazz == ArrayList.class) + return List; if (clazz == int.class || clazz == Integer.class) return Integer; if (clazz == boolean.class || clazz == Boolean.class) diff --git a/src/org/microg/safeparcel/SafeParcelWriter.java b/src/org/microg/safeparcel/SafeParcelWriter.java index 19bcd92..ad449a9 100644 --- a/src/org/microg/safeparcel/SafeParcelWriter.java +++ b/src/org/microg/safeparcel/SafeParcelWriter.java @@ -25,211 +25,211 @@ import java.util.List; public class SafeParcelWriter { - private static void writeStart(Parcel parcel, int position, int length) { - if (length >= 65535) { - parcel.writeInt(0xFFFF0000 | position); - parcel.writeInt(length); - } else { - parcel.writeInt(length << 16 | position); - } - } + private static void writeStart(Parcel parcel, int position, int length) { + if (length >= 65535) { + parcel.writeInt(0xFFFF0000 | position); + parcel.writeInt(length); + } else { + parcel.writeInt(length << 16 | position); + } + } - public static int writeStart(Parcel parcel) { - return writeStart(parcel, SafeParcelable.SAFE_PARCEL_MAGIC); - } + public static int writeStart(Parcel parcel) { + return writeStart(parcel, SafeParcelable.SAFE_PARCEL_MAGIC); + } - private static int writeStart(Parcel parcel, int position) { - parcel.writeInt(0xFFFF0000 | position); - parcel.writeInt(0); - return parcel.dataPosition(); - } + private static int writeStart(Parcel parcel, int position) { + parcel.writeInt(0xFFFF0000 | position); + parcel.writeInt(0); + return parcel.dataPosition(); + } - public static void writeEnd(Parcel parcel, int start) { - int end = parcel.dataPosition(); - int length = end - start; - parcel.setDataPosition(start - 4); - parcel.writeInt(length); - parcel.setDataPosition(end); - } + public static void writeEnd(Parcel parcel, int start) { + int end = parcel.dataPosition(); + int length = end - start; + parcel.setDataPosition(start - 4); + parcel.writeInt(length); + parcel.setDataPosition(end); + } - public static void write(Parcel parcel, int position, Boolean val) { - if (val == null) return; - writeStart(parcel, position, 4); - parcel.writeInt(val ? 1 : 0); - } + public static void write(Parcel parcel, int position, Boolean val) { + if (val == null) return; + writeStart(parcel, position, 4); + parcel.writeInt(val ? 1 : 0); + } - public static void write(Parcel parcel, int position, Byte val) { - if (val == null) return; - writeStart(parcel, position, 4); - parcel.writeInt(val); - } + public static void write(Parcel parcel, int position, Byte val) { + if (val == null) return; + writeStart(parcel, position, 4); + parcel.writeInt(val); + } - public static void write(Parcel parcel, int position, Short val) { - if (val == null) return; - writeStart(parcel, position, 4); - parcel.writeInt(val); - } + public static void write(Parcel parcel, int position, Short val) { + if (val == null) return; + writeStart(parcel, position, 4); + parcel.writeInt(val); + } - public static void write(Parcel parcel, int position, Integer val) { - if (val == null) return; - writeStart(parcel, position, 4); - parcel.writeInt(val); - } + public static void write(Parcel parcel, int position, Integer val) { + if (val == null) return; + writeStart(parcel, position, 4); + parcel.writeInt(val); + } - public static void write(Parcel parcel, int position, Long val) { - if (val == null) return; - writeStart(parcel, position, 8); - parcel.writeLong(val); - } + public static void write(Parcel parcel, int position, Long val) { + if (val == null) return; + writeStart(parcel, position, 8); + parcel.writeLong(val); + } - public static void write(Parcel parcel, int position, Float val) { - if (val == null) return; - writeStart(parcel, position, 4); - parcel.writeFloat(val); - } + public static void write(Parcel parcel, int position, Float val) { + if (val == null) return; + writeStart(parcel, position, 4); + parcel.writeFloat(val); + } - public static void write(Parcel parcel, int position, Double val) { - if (val == null) return; - writeStart(parcel, position, 8); - parcel.writeDouble(val); - } + public static void write(Parcel parcel, int position, Double val) { + if (val == null) return; + writeStart(parcel, position, 8); + parcel.writeDouble(val); + } - public static void write(Parcel parcel, int position, String val, boolean mayNull) { - if (val == null) { - if (mayNull) { - writeStart(parcel, position, 0); - } - } else { - int start = writeStart(parcel, position); - parcel.writeString(val); - writeEnd(parcel, start); - } - } + public static void write(Parcel parcel, int position, String val, boolean mayNull) { + if (val == null) { + if (mayNull) { + writeStart(parcel, position, 0); + } + } else { + int start = writeStart(parcel, position); + parcel.writeString(val); + writeEnd(parcel, start); + } + } - public static void write(Parcel parcel, int position, Parcelable val, int flags, boolean mayNull) { - if (val == null) { - if (mayNull) { - writeStart(parcel, position, 0); - } - } else { - int start = writeStart(parcel, position); - val.writeToParcel(parcel, flags); - writeEnd(parcel, start); - } - } + public static void write(Parcel parcel, int position, Parcelable val, int flags, boolean mayNull) { + if (val == null) { + if (mayNull) { + writeStart(parcel, position, 0); + } + } else { + int start = writeStart(parcel, position); + val.writeToParcel(parcel, flags); + writeEnd(parcel, start); + } + } - public static void write(Parcel parcel, int position, Bundle val, boolean mayNull) { - if (val == null) { - if (mayNull) { - writeStart(parcel, position, 0); - } - } else { - int start = writeStart(parcel, position); - parcel.writeBundle(val); - writeEnd(parcel, start); - } - } + public static void write(Parcel parcel, int position, Bundle val, boolean mayNull) { + if (val == null) { + if (mayNull) { + writeStart(parcel, position, 0); + } + } else { + int start = writeStart(parcel, position); + parcel.writeBundle(val); + writeEnd(parcel, start); + } + } - public static void write(Parcel parcel, int position, byte[] val, boolean mayNull) { - if (val == null) { - if (mayNull) { - writeStart(parcel, position, 0); - } - } else { - int start = writeStart(parcel, position); - parcel.writeByteArray(val); - writeEnd(parcel, start); - } - } + public static void write(Parcel parcel, int position, byte[] val, boolean mayNull) { + if (val == null) { + if (mayNull) { + writeStart(parcel, position, 0); + } + } else { + int start = writeStart(parcel, position); + parcel.writeByteArray(val); + writeEnd(parcel, start); + } + } - public static void write(Parcel parcel, int position, String[] val, boolean mayNull) { - if (val == null) { - if (mayNull) { - writeStart(parcel, position, 0); - } - } else { - int start = writeStart(parcel, position); - parcel.writeStringArray(val); - writeEnd(parcel, start); - } - } + public static void write(Parcel parcel, int position, String[] val, boolean mayNull) { + if (val == null) { + if (mayNull) { + writeStart(parcel, position, 0); + } + } else { + int start = writeStart(parcel, position); + parcel.writeStringArray(val); + writeEnd(parcel, start); + } + } - public static void writeStringList(Parcel parcel, int position, List val, boolean mayNull) { - if (val == null) { - if (mayNull) { - writeStart(parcel, position, 0); - } - } else { - int start = writeStart(parcel, position); - parcel.writeStringList(val); - writeEnd(parcel, start); - } - } + public static void writeStringList(Parcel parcel, int position, List val, boolean mayNull) { + if (val == null) { + if (mayNull) { + writeStart(parcel, position, 0); + } + } else { + int start = writeStart(parcel, position); + parcel.writeStringList(val); + writeEnd(parcel, start); + } + } - private static void writeArrayPart(Parcel parcel, T val, int flags) { - int before = parcel.dataPosition(); - parcel.writeInt(1); - int start = parcel.dataPosition(); - val.writeToParcel(parcel, flags); - int end = parcel.dataPosition(); - parcel.setDataPosition(before); - parcel.writeInt(end - start); - parcel.setDataPosition(end); - } + private static void writeArrayPart(Parcel parcel, T val, int flags) { + int before = parcel.dataPosition(); + parcel.writeInt(1); + int start = parcel.dataPosition(); + val.writeToParcel(parcel, flags); + int end = parcel.dataPosition(); + parcel.setDataPosition(before); + parcel.writeInt(end - start); + parcel.setDataPosition(end); + } - public static void write(Parcel parcel, int position, T[] val, int flags, boolean mayNull) { - if (val == null) { - if (mayNull) { - writeStart(parcel, position, 0); - } - } else { - int start = writeStart(parcel, position); - parcel.writeInt(val.length); - for (T t : val) { - if (t == null) { - parcel.writeInt(0); - } else { - writeArrayPart(parcel, t, flags); - } - } - writeEnd(parcel, start); - } - } + public static void write(Parcel parcel, int position, T[] val, int flags, boolean mayNull) { + if (val == null) { + if (mayNull) { + writeStart(parcel, position, 0); + } + } else { + int start = writeStart(parcel, position); + parcel.writeInt(val.length); + for (T t : val) { + if (t == null) { + parcel.writeInt(0); + } else { + writeArrayPart(parcel, t, flags); + } + } + writeEnd(parcel, start); + } + } - public static void write(Parcel parcel, int position, Parcel val, boolean mayNull) { - if (val == null) { - if (mayNull) { - writeStart(parcel, position, 0); - } - } else { - int start = writeStart(parcel, position); - parcel.appendFrom(val, 0, val.dataSize()); - writeEnd(parcel, start); - } - } + public static void write(Parcel parcel, int position, Parcel val, boolean mayNull) { + if (val == null) { + if (mayNull) { + writeStart(parcel, position, 0); + } + } else { + int start = writeStart(parcel, position); + parcel.appendFrom(val, 0, val.dataSize()); + writeEnd(parcel, start); + } + } - public static void write(Parcel parcel, int position, List val, boolean mayNull) { - if (val == null) { - if (mayNull) { - writeStart(parcel, position, 0); - } - } else { - int start = writeStart(parcel, position); - parcel.writeList(val); - writeEnd(parcel, start); - } - } + public static void write(Parcel parcel, int position, List val, boolean mayNull) { + if (val == null) { + if (mayNull) { + writeStart(parcel, position, 0); + } + } else { + int start = writeStart(parcel, position); + parcel.writeList(val); + writeEnd(parcel, start); + } + } - public static void write(Parcel parcel, int position, IBinder val, boolean mayNull) { - if (val == null) { - if (mayNull) { - writeStart(parcel, position, 0); - } - } else { - int start = writeStart(parcel, position); - parcel.writeStrongBinder(val); - writeEnd(parcel, start); - } - } + public static void write(Parcel parcel, int position, IBinder val, boolean mayNull) { + if (val == null) { + if (mayNull) { + writeStart(parcel, position, 0); + } + } else { + int start = writeStart(parcel, position); + parcel.writeStrongBinder(val); + writeEnd(parcel, start); + } + } } diff --git a/src/org/microg/safeparcel/SafeParcelable.java b/src/org/microg/safeparcel/SafeParcelable.java index ac9cc30..a99c2a0 100644 --- a/src/org/microg/safeparcel/SafeParcelable.java +++ b/src/org/microg/safeparcel/SafeParcelable.java @@ -19,6 +19,6 @@ package org.microg.safeparcel; import android.os.Parcelable; public interface SafeParcelable extends Parcelable { - public static final String NULL = "SAFE_PARCELABLE_NULL_STRING"; - int SAFE_PARCEL_MAGIC = 20293; + public static final String NULL = "SAFE_PARCELABLE_NULL_STRING"; + int SAFE_PARCEL_MAGIC = 20293; } diff --git a/src/org/microg/safeparcel/SafeParceled.java b/src/org/microg/safeparcel/SafeParceled.java index fb86600..e2c63fb 100644 --- a/src/org/microg/safeparcel/SafeParceled.java +++ b/src/org/microg/safeparcel/SafeParceled.java @@ -11,4 +11,6 @@ public @interface SafeParceled { int value(); boolean mayNull() default false; + + String subType() default "undefined"; }