1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.dialer.protos; 18 19 import android.content.ContentValues; 20 import android.content.Intent; 21 import android.os.Bundle; 22 import android.support.annotation.NonNull; 23 import com.android.dialer.common.Assert; 24 import com.google.protobuf.InvalidProtocolBufferException; 25 import com.google.protobuf.MessageLite; 26 27 /** Useful methods for using Protocol Buffers with Android. */ 28 public final class ProtoParsers { 29 ProtoParsers()30 private ProtoParsers() {} 31 32 /** Retrieve a proto from a Bundle which was not created within the current executable/version. */ 33 @SuppressWarnings("unchecked") // We want to eventually optimize away parser classes, so cast get( @onNull Bundle bundle, @NonNull String key, @NonNull T defaultInstance)34 public static <T extends MessageLite> T get( 35 @NonNull Bundle bundle, @NonNull String key, @NonNull T defaultInstance) 36 throws InvalidProtocolBufferException { 37 38 Assert.isNotNull(bundle); 39 Assert.isNotNull(key); 40 Assert.isNotNull(defaultInstance); 41 42 byte[] bytes = bundle.getByteArray(key); 43 return (T) mergeFrom(bytes, defaultInstance.getDefaultInstanceForType()); 44 } 45 46 /** 47 * Retrieve a proto from a ContentValues which was not created within the current 48 * executable/version. 49 */ 50 @SuppressWarnings("unchecked") // We want to eventually optimize away parser classes, so cast get( @onNull ContentValues contentValues, @NonNull String key, @NonNull T defaultInstance)51 public static <T extends MessageLite> T get( 52 @NonNull ContentValues contentValues, @NonNull String key, @NonNull T defaultInstance) 53 throws InvalidProtocolBufferException { 54 55 Assert.isNotNull(contentValues); 56 Assert.isNotNull(key); 57 Assert.isNotNull(defaultInstance); 58 59 byte[] bytes = contentValues.getAsByteArray(key); 60 return (T) mergeFrom(bytes, defaultInstance.getDefaultInstanceForType()); 61 } 62 63 /** 64 * Retrieve a proto from a trusted bundle which was created within the current executable/version. 65 * 66 * @throws IllegalStateException if the proto cannot be parsed 67 */ getTrusted( @onNull Bundle bundle, @NonNull String key, @NonNull T defaultInstance)68 public static <T extends MessageLite> T getTrusted( 69 @NonNull Bundle bundle, @NonNull String key, @NonNull T defaultInstance) { 70 try { 71 return get(bundle, key, defaultInstance); 72 } catch (InvalidProtocolBufferException e) { 73 throw Assert.createIllegalStateFailException(e.toString()); 74 } 75 } 76 77 /** 78 * Retrieve a proto from a trusted ContentValues which was created within the current 79 * executable/version. 80 * 81 * @throws IllegalStateException if the proto cannot be parsed 82 */ getTrusted( @onNull ContentValues contentValues, @NonNull String key, @NonNull T defaultInstance)83 public static <T extends MessageLite> T getTrusted( 84 @NonNull ContentValues contentValues, @NonNull String key, @NonNull T defaultInstance) { 85 try { 86 return get(contentValues, key, defaultInstance); 87 } catch (InvalidProtocolBufferException e) { 88 throw Assert.createIllegalStateFailException(e.toString()); 89 } 90 } 91 92 /** 93 * Retrieve a proto from a trusted bundle which was created within the current executable/version. 94 * 95 * @throws RuntimeException if the proto cannot be parsed 96 */ getTrusted( @onNull Intent intent, @NonNull String key, @NonNull T defaultInstance)97 public static <T extends MessageLite> T getTrusted( 98 @NonNull Intent intent, @NonNull String key, @NonNull T defaultInstance) { 99 Assert.isNotNull(intent); 100 return getTrusted(intent.getExtras(), key, defaultInstance); 101 } 102 103 /** 104 * Stores a proto in a Bundle, for later retrieval by {@link #get(Bundle, String, MessageLite)} or 105 * {@link #getFromInstanceState(Bundle, String, MessageLite)}. 106 */ put( @onNull Bundle bundle, @NonNull String key, @NonNull MessageLite message)107 public static void put( 108 @NonNull Bundle bundle, @NonNull String key, @NonNull MessageLite message) { 109 Assert.isNotNull(message); 110 Assert.isNotNull(bundle); 111 Assert.isNotNull(key); 112 bundle.putByteArray(key, message.toByteArray()); 113 } 114 115 /** 116 * Stores a proto in an Intent, for later retrieval by {@link #get(Bundle, String, MessageLite)}. 117 * Needs separate method because Intent has similar to but different API than Bundle. 118 */ put( @onNull Intent intent, @NonNull String key, @NonNull MessageLite message)119 public static void put( 120 @NonNull Intent intent, @NonNull String key, @NonNull MessageLite message) { 121 Assert.isNotNull(message); 122 Assert.isNotNull(intent); 123 Assert.isNotNull(key); 124 intent.putExtra(key, message.toByteArray()); 125 } 126 127 /** Parses a proto, throwing parser errors as runtime exceptions. */ 128 @SuppressWarnings("unchecked") // We want to eventually optimize away parser classes mergeFrom(byte[] bytes, T defaultInstance)129 private static <T extends MessageLite> T mergeFrom(byte[] bytes, T defaultInstance) { 130 try { 131 return (T) defaultInstance.toBuilder().mergeFrom(bytes).build(); 132 } catch (InvalidProtocolBufferException e) { 133 throw Assert.createIllegalStateFailException(e.toString()); 134 } 135 } 136 } 137