• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 android.util.proto;
18 
19 import android.annotation.IntDef;
20 import android.annotation.LongDef;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 
24 import java.lang.annotation.Retention;
25 import java.lang.annotation.RetentionPolicy;
26 
27 /**
28  * Base utility class for protobuf streams.
29  *
30  * Contains a set of constants and methods used in generated code for
31  * {@link ProtoOutputStream}.
32  *
33  * @hide
34  */
35 public class ProtoStream {
36 
37     /**
38      * A protobuf wire type.  All application-level types are represented using
39      * varint, fixed64, length-delimited and fixed32 wire types. The start-group
40      * and end-group types are unused in modern protobuf versions (proto2 and proto3),
41      * but are included here for completeness.
42      *
43      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
44      * Encoding</a>
45      */
46     @Retention(RetentionPolicy.SOURCE)
47     @IntDef({
48         WIRE_TYPE_VARINT,
49         WIRE_TYPE_FIXED64,
50         WIRE_TYPE_LENGTH_DELIMITED,
51         WIRE_TYPE_START_GROUP,
52         WIRE_TYPE_END_GROUP,
53         WIRE_TYPE_FIXED32
54     })
55     public @interface WireType {}
56 
57     /**
58      * Application-level protobuf field types, as would be used in a .proto file.
59      *
60      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
61      * Encoding</a>
62      */
63     @Retention(RetentionPolicy.SOURCE)
64     @LongDef({
65         FIELD_TYPE_UNKNOWN,
66         FIELD_TYPE_DOUBLE,
67         FIELD_TYPE_FLOAT,
68         FIELD_TYPE_INT64,
69         FIELD_TYPE_UINT64,
70         FIELD_TYPE_INT32,
71         FIELD_TYPE_FIXED64,
72         FIELD_TYPE_FIXED32,
73         FIELD_TYPE_BOOL,
74         FIELD_TYPE_STRING,
75         FIELD_TYPE_MESSAGE,
76         FIELD_TYPE_BYTES,
77         FIELD_TYPE_UINT32,
78         FIELD_TYPE_ENUM,
79         FIELD_TYPE_SFIXED32,
80         FIELD_TYPE_SFIXED64,
81         FIELD_TYPE_SINT32,
82         FIELD_TYPE_SINT64,
83     })
84     public @interface FieldType {}
85 
86 
87     /**
88      * Represents the cardinality of a protobuf field.
89      *
90      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
91      * Encoding</a>
92      */
93     @Retention(RetentionPolicy.SOURCE)
94     @LongDef({
95         FIELD_COUNT_UNKNOWN,
96         FIELD_COUNT_SINGLE,
97         FIELD_COUNT_REPEATED,
98         FIELD_COUNT_PACKED,
99     })
100     public @interface FieldCount {}
101 
102     /**
103      * Number of bits to shift the field number to form a tag.
104      *
105      * <pre>
106      * // Reading a field number from a tag.
107      * int fieldNumber = tag &gt;&gt;&gt; FIELD_ID_SHIFT;
108      *
109      * // Building a tag from a field number and a wire type.
110      * int tag = (fieldNumber &lt;&lt; FIELD_ID_SHIFT) | wireType;
111      * </pre>
112      *
113      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
114      * Encoding</a>
115      */
116     public static final int FIELD_ID_SHIFT = 3;
117 
118     /**
119      * Mask to select the wire type from a tag.
120      *
121      * <pre>
122      * // Reading a wire type from a tag.
123      * int wireType = tag &amp; WIRE_TYPE_MASK;
124      *
125      * // Building a tag from a field number and a wire type.
126      * int tag = (fieldNumber &lt;&lt; FIELD_ID_SHIFT) | wireType;
127      * </pre>
128      *
129      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
130      * Encoding</a>
131      */
132     public static final int WIRE_TYPE_MASK = (1 << FIELD_ID_SHIFT) - 1;
133 
134     /**
135      * Mask to select the field id from a tag.
136      * @hide (not used by anything, and not actually useful, because you also want
137      * to shift when you mask the field id).
138      */
139     public static final int FIELD_ID_MASK = ~WIRE_TYPE_MASK;
140 
141     /**
142      * Varint wire type code.
143      *
144      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
145      * Encoding</a>
146      */
147     public static final int WIRE_TYPE_VARINT = 0;
148 
149     /**
150      * Fixed64 wire type code.
151      *
152      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
153      * Encoding</a>
154      */
155     public static final int WIRE_TYPE_FIXED64 = 1;
156 
157     /**
158      * Length delimited wire type code.
159      *
160      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
161      * Encoding</a>
162      */
163     public static final int WIRE_TYPE_LENGTH_DELIMITED = 2;
164 
165     /**
166      * Start group wire type code.
167      *
168      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
169      * Encoding</a>
170      */
171     public static final int WIRE_TYPE_START_GROUP = 3;
172 
173     /**
174      * End group wire type code.
175      *
176      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
177      * Encoding</a>
178      */
179     public static final int WIRE_TYPE_END_GROUP = 4;
180 
181     /**
182      * Fixed32 wire type code.
183      *
184      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
185      * Encoding</a>
186      */
187     public static final int WIRE_TYPE_FIXED32 = 5;
188 
189     /**
190      * Position of the field type in a (long) fieldId.
191      */
192     public static final int FIELD_TYPE_SHIFT = 32;
193 
194     /**
195      * Mask for the field types stored in a fieldId.  Leaves a whole
196      * byte for future expansion, even though there are currently only 17 types.
197      */
198     public static final long FIELD_TYPE_MASK = 0x0ffL << FIELD_TYPE_SHIFT;
199 
200     /**
201      * Not a real field type.
202      * @hide
203      */
204     public static final long FIELD_TYPE_UNKNOWN = 0;
205 
206 
207     /*
208      * The FIELD_TYPE_ constants are copied from
209      * external/protobuf/src/google/protobuf/descriptor.h directly, so no
210      * extra mapping needs to be maintained in this case.
211      */
212 
213     /**
214      * Field type code for double fields. Used to build constants in generated
215      * code for use with the {@link ProtoOutputStream#write(long, double)
216      * ProtoOutputStream.write(long, double)} method.
217      */
218     public static final long FIELD_TYPE_DOUBLE = 1L << FIELD_TYPE_SHIFT;
219 
220     /**
221      * Field type code for float fields. Used to build constants in generated
222      * code for use with the {@link ProtoOutputStream#write(long, float)
223      * ProtoOutputStream.write(long, float)} method.
224      */
225     public static final long FIELD_TYPE_FLOAT = 2L << FIELD_TYPE_SHIFT;
226 
227     /**
228      * Field type code for int64 fields. Used to build constants in generated
229      * code for use with the {@link ProtoOutputStream#write(long, long)
230      * ProtoOutputStream.write(long, long)} method.
231      */
232     public static final long FIELD_TYPE_INT64 = 3L << FIELD_TYPE_SHIFT;
233 
234     /**
235      * Field type code for uint64 fields. Used to build constants in generated
236      * code for use with the {@link ProtoOutputStream#write(long, long)
237      * ProtoOutputStream.write(long, long)} method.
238      */
239     public static final long FIELD_TYPE_UINT64 = 4L << FIELD_TYPE_SHIFT;
240 
241     /**
242      * Field type code for int32 fields. Used to build constants in generated
243      * code for use with the {@link ProtoOutputStream#write(long, int)
244      * ProtoOutputStream.write(long, int)} method.
245      */
246     public static final long FIELD_TYPE_INT32 = 5L << FIELD_TYPE_SHIFT;
247 
248     /**
249      * Field type code for fixed64 fields. Used to build constants in generated
250      * code for use with the {@link ProtoOutputStream#write(long, long)
251      * ProtoOutputStream.write(long, long)} method.
252      */
253     public static final long FIELD_TYPE_FIXED64 = 6L << FIELD_TYPE_SHIFT;
254 
255     /**
256      * Field type code for fixed32 fields. Used to build constants in generated
257      * code for use with the {@link ProtoOutputStream#write(long, int)
258      * ProtoOutputStream.write(long, int)} method.
259      */
260 
261     /**
262      * Field type code for fixed32 fields. Used to build constants in generated
263      * code for use with the {@link ProtoOutputStream#write(long, int)
264      * ProtoOutputStream.write(long, int)} method.
265      */
266     public static final long FIELD_TYPE_FIXED32 = 7L << FIELD_TYPE_SHIFT;
267 
268     /**
269      * Field type code for bool fields. Used to build constants in generated
270      * code for use with the {@link ProtoOutputStream#write(long, boolean)
271      * ProtoOutputStream.write(long, boolean)} method.
272      */
273     public static final long FIELD_TYPE_BOOL = 8L << FIELD_TYPE_SHIFT;
274 
275     /**
276      * Field type code for string fields. Used to build constants in generated
277      * code for use with the {@link ProtoOutputStream#write(long, String)
278      * ProtoOutputStream.write(long, String)} method.
279      */
280     public static final long FIELD_TYPE_STRING = 9L << FIELD_TYPE_SHIFT;
281 
282     //  public static final long FIELD_TYPE_GROUP = 10L << FIELD_TYPE_SHIFT; // Deprecated.
283 
284     /**
285      * Field type code for message fields. Used to build constants in generated
286      * code for use with the {@link ProtoOutputStream#start(long)
287      * ProtoOutputStream.start(long)} method.
288      */
289     public static final long FIELD_TYPE_MESSAGE = 11L << FIELD_TYPE_SHIFT;
290 
291     /**
292      * Field type code for bytes fields. Used to build constants in generated
293      * code for use with the {@link ProtoOutputStream#write(long, byte[])
294      * ProtoOutputStream.write(long, byte[])} method.
295      */
296     public static final long FIELD_TYPE_BYTES = 12L << FIELD_TYPE_SHIFT;
297 
298     /**
299      * Field type code for uint32 fields. Used to build constants in generated
300      * code for use with the {@link ProtoOutputStream#write(long, int)
301      * ProtoOutputStream.write(long, int)} method.
302      */
303     public static final long FIELD_TYPE_UINT32 = 13L << FIELD_TYPE_SHIFT;
304 
305     /**
306      * Field type code for enum fields. Used to build constants in generated
307      * code for use with the {@link ProtoOutputStream#write(long, int)
308      * ProtoOutputStream.write(long, int)} method.
309      */
310     public static final long FIELD_TYPE_ENUM = 14L << FIELD_TYPE_SHIFT;
311 
312     /**
313      * Field type code for sfixed32 fields. Used to build constants in generated
314      * code for use with the {@link ProtoOutputStream#write(long, int)
315      * ProtoOutputStream.write(long, int)} method.
316      */
317     public static final long FIELD_TYPE_SFIXED32 = 15L << FIELD_TYPE_SHIFT;
318 
319     /**
320      * Field type code for sfixed64 fields. Used to build constants in generated
321      * code for use with the {@link ProtoOutputStream#write(long, long)
322      * ProtoOutputStream.write(long, long)} method.
323      */
324     public static final long FIELD_TYPE_SFIXED64 = 16L << FIELD_TYPE_SHIFT;
325 
326     /**
327      * Field type code for sint32 fields. Used to build constants in generated
328      * code for use with the {@link ProtoOutputStream#write(long, int)
329      * ProtoOutputStream.write(long, int)} method.
330      */
331     public static final long FIELD_TYPE_SINT32 = 17L << FIELD_TYPE_SHIFT;
332 
333     /**
334      * Field type code for sint64 fields. Used to build constants in generated
335      * code for use with the {@link ProtoOutputStream#write(long, long)
336      * ProtoOutputStream.write(long, long)} method.
337      */
338     public static final long FIELD_TYPE_SINT64 = 18L << FIELD_TYPE_SHIFT;
339 
340     private static final @NonNull String[] FIELD_TYPE_NAMES = new String[]{
341             "Double",
342             "Float",
343             "Int64",
344             "UInt64",
345             "Int32",
346             "Fixed64",
347             "Fixed32",
348             "Bool",
349             "String",
350             "Group",  // This field is deprecated but reserved here for indexing.
351             "Message",
352             "Bytes",
353             "UInt32",
354             "Enum",
355             "SFixed32",
356             "SFixed64",
357             "SInt32",
358             "SInt64",
359     };
360 
361     //
362     // FieldId flags for whether the field is single, repeated or packed.
363     //
364     /**
365      * Bit offset for building a field id to be used with a
366      * <code>{@link ProtoOutputStream}.write(...)</code>.
367      *
368      * @see #FIELD_COUNT_MASK
369      * @see #FIELD_COUNT_UNKNOWN
370      * @see #FIELD_COUNT_SINGLE
371      * @see #FIELD_COUNT_REPEATED
372      * @see #FIELD_COUNT_PACKED
373      */
374     public static final int FIELD_COUNT_SHIFT = 40;
375 
376     /**
377      * Bit mask for selecting the field count when reading a field id that
378      * is used with a <code>{@link ProtoOutputStream}.write(...)</code> method.
379      *
380      * @see #FIELD_COUNT_SHIFT
381      * @see #FIELD_COUNT_MASK
382      * @see #FIELD_COUNT_UNKNOWN
383      * @see #FIELD_COUNT_SINGLE
384      * @see #FIELD_COUNT_REPEATED
385      * @see #FIELD_COUNT_PACKED
386      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
387      * Encoding</a>
388      */
389     public static final long FIELD_COUNT_MASK = 0x0fL << FIELD_COUNT_SHIFT;
390 
391     /**
392      * Unknown field count, encoded into a field id used with a
393      * <code>{@link ProtoOutputStream}.write(...)</code> method.
394      *
395      * @see #FIELD_COUNT_SHIFT
396      * @see #FIELD_COUNT_MASK
397      * @see #FIELD_COUNT_SINGLE
398      * @see #FIELD_COUNT_REPEATED
399      * @see #FIELD_COUNT_PACKED
400      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
401      * Encoding</a>
402      */
403     public static final long FIELD_COUNT_UNKNOWN = 0;
404 
405     /**
406      * Single field count, encoded into a field id used with a
407      * <code>{@link ProtoOutputStream}.write(...)</code> method.
408      *
409      * @see #FIELD_COUNT_SHIFT
410      * @see #FIELD_COUNT_MASK
411      * @see #FIELD_COUNT_UNKNOWN
412      * @see #FIELD_COUNT_REPEATED
413      * @see #FIELD_COUNT_PACKED
414      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
415      * Encoding</a>
416      */
417     public static final long FIELD_COUNT_SINGLE = 1L << FIELD_COUNT_SHIFT;
418 
419     /**
420      * Repeated field count, encoded into a field id used with a
421      * <code>{@link ProtoOutputStream}.write(...)</code> method.
422      *
423      * @see #FIELD_COUNT_SHIFT
424      * @see #FIELD_COUNT_MASK
425      * @see #FIELD_COUNT_UNKNOWN
426      * @see #FIELD_COUNT_SINGLE
427      * @see #FIELD_COUNT_PACKED
428      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
429      * Encoding</a>
430      */
431     public static final long FIELD_COUNT_REPEATED = 2L << FIELD_COUNT_SHIFT;
432 
433     /**
434      * Repeated packed field count, encoded into a field id used with a
435      * <code>{@link ProtoOutputStream}.write(...)</code> method.
436      *
437      * @see #FIELD_COUNT_SHIFT
438      * @see #FIELD_COUNT_MASK
439      * @see #FIELD_COUNT_UNKNOWN
440      * @see #FIELD_COUNT_SINGLE
441      * @see #FIELD_COUNT_REPEATED
442      * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
443      * Encoding</a>
444      */
445     public static final long FIELD_COUNT_PACKED = 5L << FIELD_COUNT_SHIFT;
446 
447 
448     /**
449      * Get the developer-usable name of a field type.
450      */
getFieldTypeString(@ieldType long fieldType)451     public static @Nullable String getFieldTypeString(@FieldType long fieldType) {
452         int index = ((int) ((fieldType & FIELD_TYPE_MASK) >>> FIELD_TYPE_SHIFT)) - 1;
453         if (index >= 0 && index < FIELD_TYPE_NAMES.length) {
454             return FIELD_TYPE_NAMES[index];
455         } else {
456             return null;
457         }
458     }
459 
460     /**
461      * Get the developer-usable name of a field count.
462      */
getFieldCountString(long fieldCount)463     public static @Nullable String getFieldCountString(long fieldCount) {
464         if (fieldCount == FIELD_COUNT_SINGLE) {
465             return "";
466         } else if (fieldCount == FIELD_COUNT_REPEATED) {
467             return "Repeated";
468         } else if (fieldCount == FIELD_COUNT_PACKED) {
469             return "Packed";
470         } else {
471             return null;
472         }
473     }
474 
475     /**
476      * Get the developer-usable name of a wire type.
477      */
getWireTypeString(@ireType int wireType)478     public static @Nullable String getWireTypeString(@WireType int wireType) {
479         switch (wireType) {
480             case WIRE_TYPE_VARINT:
481                 return "Varint";
482             case WIRE_TYPE_FIXED64:
483                 return "Fixed64";
484             case WIRE_TYPE_LENGTH_DELIMITED:
485                 return "Length Delimited";
486             case WIRE_TYPE_START_GROUP:
487                 return "Start Group";
488             case WIRE_TYPE_END_GROUP:
489                 return "End Group";
490             case WIRE_TYPE_FIXED32:
491                 return "Fixed32";
492             default:
493                 return null;
494         }
495     }
496 
497     /**
498      * Get a debug string for a fieldId.
499      */
getFieldIdString(long fieldId)500     public static @NonNull String getFieldIdString(long fieldId) {
501         final long fieldCount = fieldId & FIELD_COUNT_MASK;
502         String countString = getFieldCountString(fieldCount);
503         if (countString == null) {
504             countString = "fieldCount=" + fieldCount;
505         }
506         if (countString.length() > 0) {
507             countString += " ";
508         }
509 
510         final long fieldType = fieldId & FIELD_TYPE_MASK;
511         String typeString = getFieldTypeString(fieldType);
512         if (typeString == null) {
513             typeString = "fieldType=" + fieldType;
514         }
515 
516         return countString + typeString + " tag=" + ((int) fieldId)
517                 + " fieldId=0x" + Long.toHexString(fieldId);
518     }
519 
520     /**
521      * Combine a fieldId (the field keys in the proto file) and the field flags.
522      * Mostly useful for testing because the generated code contains the fieldId
523      * constants.
524      */
makeFieldId(int id, long fieldFlags)525     public static long makeFieldId(int id, long fieldFlags) {
526         return fieldFlags | (((long) id) & 0x0ffffffffL);
527     }
528 
529     //
530     // Child objects
531     //
532 
533     /**
534      * Make a token.
535      * Bits 61-63 - tag size (So we can go backwards later if the object had not data)
536      *            - 3 bits, max value 7, max value needed 5
537      * Bit  60    - true if the object is repeated (lets us require endObject or endRepeatedObject)
538      * Bits 59-51 - depth (For error checking)
539      *            - 9 bits, max value 512, when checking, value is masked (if we really
540      *              are more than 512 levels deep)
541      * Bits 32-50 - objectId (For error checking)
542      *            - 19 bits, max value 524,288. that's a lot of objects. IDs will wrap
543      *              because of the overflow, and only the tokens are compared.
544      * Bits  0-31 - offset of interest for the object.
545      */
makeToken(int tagSize, boolean repeated, int depth, int objectId, int offset)546     public static long makeToken(int tagSize, boolean repeated, int depth, int objectId,
547             int offset) {
548         return ((0x07L & (long) tagSize) << 61)
549                 | (repeated ? (1L << 60) : 0)
550                 | (0x01ffL & (long) depth) << 51
551                 | (0x07ffffL & (long) objectId) << 32
552                 | (0x0ffffffffL & (long) offset);
553     }
554 
555     /**
556      * Get the encoded tag size from the token.
557      *
558      * @hide
559      */
getTagSizeFromToken(long token)560     public static int getTagSizeFromToken(long token) {
561         return (int) (0x7 & (token >> 61));
562     }
563 
564     /**
565      * Get whether the token has the repeated bit set to true or false
566      *
567      * @hide
568      */
getRepeatedFromToken(long token)569     public static boolean getRepeatedFromToken(long token) {
570         return (0x1 & (token >> 60)) != 0;
571     }
572 
573     /**
574      * Get the nesting depth from the token.
575      *
576      * @hide
577      */
getDepthFromToken(long token)578     public static int getDepthFromToken(long token) {
579         return (int) (0x01ff & (token >> 51));
580     }
581 
582     /**
583      * Get the object ID from the token.
584      *
585      * <p>The object ID is a serial number for the
586      * startObject calls that have happened on this object.  The values are truncated
587      * to 9 bits, but that is sufficient for error checking.
588      *
589      * @hide
590      */
getObjectIdFromToken(long token)591     public static int getObjectIdFromToken(long token) {
592         return (int) (0x07ffff & (token >> 32));
593     }
594 
595     /**
596      * Get the location of the offset recorded in the token.
597      *
598      * @hide
599      */
getOffsetFromToken(long token)600     public static int getOffsetFromToken(long token) {
601         return (int) token;
602     }
603 
604     /**
605      * Convert the object ID to the ordinal value -- the n-th call to startObject.
606      *
607      * <p>The object IDs start at -1 and count backwards, so that the value is unlikely
608      * to alias with an actual size field that had been written.
609      *
610      * @hide
611      */
convertObjectIdToOrdinal(int objectId)612     public static int convertObjectIdToOrdinal(int objectId) {
613         return (-1 & 0x07ffff) - objectId;
614     }
615 
616     /**
617      * Return a debugging string of a token.
618      */
token2String(long token)619     public static @NonNull String token2String(long token) {
620         if (token == 0L) {
621             return "Token(0)";
622         } else {
623             return "Token(val=0x" + Long.toHexString(token)
624                     + " depth=" + getDepthFromToken(token)
625                     + " object=" + convertObjectIdToOrdinal(getObjectIdFromToken(token))
626                     + " tagSize=" + getTagSizeFromToken(token)
627                     + " offset=" + getOffsetFromToken(token)
628                     + ')';
629         }
630     }
631 
632     /**
633      * @hide
634      */
ProtoStream()635     protected ProtoStream() {}
636 }
637