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