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.Intent; 20 import android.os.Bundle; 21 import android.support.annotation.NonNull; 22 import com.android.dialer.common.Assert; 23 import com.google.protobuf.InvalidProtocolBufferException; 24 import com.google.protobuf.MessageLite; 25 26 /** Useful methods for using Protocol Buffers with Android. */ 27 public final class ProtoParsers { 28 29 private ProtoParsers() {} 30 31 /** Retrieve a proto from a Bundle which was not created within the current executable/version. */ 32 @SuppressWarnings("unchecked") // We want to eventually optimize away parser classes, so cast 33 public static <T extends MessageLite> T get( 34 @NonNull Bundle bundle, @NonNull String key, @NonNull T defaultInstance) 35 throws InvalidProtocolBufferException { 36 37 Assert.isNotNull(bundle); 38 Assert.isNotNull(key); 39 Assert.isNotNull(defaultInstance); 40 41 byte[] bytes = bundle.getByteArray(key); 42 return (T) mergeFrom(bytes, defaultInstance.getDefaultInstanceForType()); 43 } 44 45 /** 46 * Retrieve a proto from a trusted bundle which was created within the current executable/version. 47 * 48 * @throws RuntimeException if the proto cannot be parsed 49 */ 50 public static <T extends MessageLite> T getTrusted( 51 @NonNull Bundle bundle, @NonNull String key, @NonNull T defaultInstance) { 52 try { 53 return get(bundle, key, defaultInstance); 54 } catch (InvalidProtocolBufferException e) { 55 throw Assert.createIllegalStateFailException(e.toString()); 56 } 57 } 58 59 /** 60 * Retrieve a proto from a trusted bundle which was created within the current executable/version. 61 * 62 * @throws RuntimeException if the proto cannot be parsed 63 */ 64 public static <T extends MessageLite> T getTrusted( 65 @NonNull Intent intent, @NonNull String key, @NonNull T defaultInstance) { 66 Assert.isNotNull(intent); 67 return getTrusted(intent.getExtras(), key, defaultInstance); 68 } 69 70 /** 71 * Stores a proto in a Bundle, for later retrieval by {@link #get(Bundle, String, MessageLite)} or 72 * {@link #getFromInstanceState(Bundle, String, MessageLite)}. 73 */ 74 public static void put( 75 @NonNull Bundle bundle, @NonNull String key, @NonNull MessageLite message) { 76 Assert.isNotNull(message); 77 Assert.isNotNull(bundle); 78 Assert.isNotNull(key); 79 bundle.putByteArray(key, message.toByteArray()); 80 } 81 82 /** 83 * Stores a proto in an Intent, for later retrieval by {@link #get(Bundle, String, MessageLite)}. 84 * Needs separate method because Intent has similar to but different API than Bundle. 85 */ 86 public static void put( 87 @NonNull Intent intent, @NonNull String key, @NonNull MessageLite message) { 88 Assert.isNotNull(message); 89 Assert.isNotNull(intent); 90 Assert.isNotNull(key); 91 intent.putExtra(key, message.toByteArray()); 92 } 93 94 /** Parses a proto, throwing parser errors as runtime exceptions. */ 95 @SuppressWarnings("unchecked") // We want to eventually optimize away parser classes 96 private static <T extends MessageLite> T mergeFrom(byte[] bytes, T defaultInstance) { 97 try { 98 return (T) defaultInstance.toBuilder().mergeFrom(bytes).build(); 99 } catch (InvalidProtocolBufferException e) { 100 throw Assert.createIllegalStateFailException(e.toString()); 101 } 102 } 103 } 104