diff options
Diffstat (limited to 'java/com/android/dialer/protos/ProtoParsers.java')
-rw-r--r-- | java/com/android/dialer/protos/ProtoParsers.java | 125 |
1 files changed, 13 insertions, 112 deletions
diff --git a/java/com/android/dialer/protos/ProtoParsers.java b/java/com/android/dialer/protos/ProtoParsers.java index b77c0699b..5a60799bc 100644 --- a/java/com/android/dialer/protos/ProtoParsers.java +++ b/java/com/android/dialer/protos/ProtoParsers.java @@ -18,13 +18,10 @@ package com.android.dialer.protos; import android.content.Intent; import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; +import android.support.annotation.NonNull; import com.android.dialer.common.Assert; -import com.google.protobuf.CodedOutputStream; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.MessageLite; -import java.io.IOException; /** Useful methods for using Protocol Buffers with Android. */ public final class ProtoParsers { @@ -35,11 +32,8 @@ public final class ProtoParsers { @SuppressWarnings("unchecked") // We want to eventually optimize away parser classes, so cast public static <T extends MessageLite> T get(Bundle bundle, String key, T defaultInstance) throws InvalidProtocolBufferException { - // Class loaders are unique to each Class instance, so we need to specify how to decode - // the information again, even though we set the class loaders when serializing the data. - bundle.setClassLoader(ProtoParsers.class.getClassLoader()); - InternalDontUse parcelable = bundle.getParcelable(key); - return (T) parcelable.getMessageUnsafe(defaultInstance.getDefaultInstanceForType()); + byte[] bytes = bundle.getByteArray(key); + return (T) mergeFrom(bytes, defaultInstance.getDefaultInstanceForType()); } /** @@ -51,7 +45,7 @@ public final class ProtoParsers { try { return get(bundle, key, defaultInstance); } catch (InvalidProtocolBufferException e) { - throw new RuntimeException(e); + throw Assert.createIllegalStateFailException(e.toString()); } } @@ -68,121 +62,28 @@ public final class ProtoParsers { * Stores a proto in a Bundle, for later retrieval by {@link #get(Bundle, String, MessageLite)} or * {@link #getFromInstanceState(Bundle, String, MessageLite)}. */ - public static void put(Bundle bundle, String key, MessageLite message) { - bundle.putParcelable(key, new InternalDontUse<>(null, message)); + public static void put( + @NonNull Bundle bundle, @NonNull String key, @NonNull MessageLite message) { + Assert.checkState(message != null); + bundle.putByteArray(key, message.toByteArray()); } /** * Stores a proto in an Intent, for later retrieval by {@link #get(Bundle, String, MessageLite)}. * Needs separate method because Intent has similar to but different API than Bundle. */ - public static void put(Intent intent, String key, MessageLite message) { - intent.putExtra(key, new InternalDontUse<>(null, message)); - } - - /** Returns a {@linkplain Parcelable} representation of this protobuf message. */ - public static <T extends MessageLite> ParcelableProto<T> asParcelable(T message) { - return new InternalDontUse<>(null, message); - } - - /** - * A protobuf message that can be stored in a {@link Parcel}. - * - * <p><b>Note:</b> This <code>Parcelable</code> can only be used in single app. Attempting to send - * it to another app through an <code>Intent</code> will result in an exception due to Proguard - * obfusation when the target application attempts to load the <code>ParcelableProto</code> class. - */ - public interface ParcelableProto<T extends MessageLite> extends Parcelable { - /** - * @throws IllegalStateException if the parceled data does not correspond to the defaultInstance - * type. - */ - T getMessage(T defaultInstance); - } - - /** Public because of Parcelable requirements. Do not use. */ - public static final class InternalDontUse<T extends MessageLite> implements ParcelableProto<T> { - /* One of these two fields is always populated - since the bytes field never escapes this - * object, there is no risk of concurrent modification by multiple threads, and volatile - * is sufficient to be thread-safe. */ - private volatile byte[] bytes; - private volatile T message; - - /** - * Ideally, we would have type safety here. However, a static field {@link Creator} is required - * by {@link Parcelable}. Static fields are inherently not type safe, since only 1 exists per - * class (rather than 1 per type). - */ - public static final Parcelable.Creator<InternalDontUse<?>> CREATOR = - new Creator<InternalDontUse<?>>() { - @Override - public InternalDontUse<?> createFromParcel(Parcel parcel) { - int serializedSize = parcel.readInt(); - byte[] array = new byte[serializedSize]; - parcel.readByteArray(array); - return new InternalDontUse<>(array, null); - } - - @Override - public InternalDontUse<?>[] newArray(int i) { - return new InternalDontUse[i]; - } - }; - - private InternalDontUse(byte[] bytes, T message) { - Assert.checkArgument(bytes != null || message != null, "Must have a message or bytes"); - this.bytes = bytes; - this.message = message; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel parcel, int i) { - if (bytes == null) { - final byte[] flatArray = new byte[message.getSerializedSize()]; - try { - message.writeTo(CodedOutputStream.newInstance(flatArray)); - bytes = flatArray; - } catch (IOException impossible) { - throw new AssertionError(impossible); - } - } - parcel.writeInt(bytes.length); - parcel.writeByteArray(bytes); - } - - @Override - public T getMessage(T defaultInstance) { - try { - // The proto should never be invalid if it came from our application, so if it is, throw. - return getMessageUnsafe(defaultInstance); - } catch (InvalidProtocolBufferException e) { - throw new IllegalStateException(e); - } - } - - @SuppressWarnings("unchecked") // We're being deserialized, so there's no real type safety - T getMessageUnsafe(T defaultInstance) throws InvalidProtocolBufferException { - // There's a risk that we'll double-parse the bytes, but that's OK, because it'll end up - // as the same immutable object anyway. - if (message == null) { - message = (T) defaultInstance.toBuilder().mergeFrom(bytes).build(); - } - return message; - } + public static void put(@NonNull Intent intent, @NonNull String key, MessageLite message) { + Assert.checkState(message != null); + intent.putExtra(key, message.toByteArray()); } /** Parses a proto, throwing parser errors as runtime exceptions. */ @SuppressWarnings("unchecked") // We want to eventually optimize away parser classes - public static <T extends MessageLite> T mergeFrom(byte[] bytes, T defaultInstance) { + private static <T extends MessageLite> T mergeFrom(byte[] bytes, T defaultInstance) { try { return (T) defaultInstance.toBuilder().mergeFrom(bytes).build(); } catch (InvalidProtocolBufferException e) { - throw new RuntimeException(e); + throw Assert.createIllegalStateFailException(e.toString()); } } } |