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