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