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 >>> FIELD_ID_SHIFT; 113 * 114 * // Building a tag from a field number and a wire type. 115 * int tag = (fieldNumber << 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 & WIRE_TYPE_MASK; 129 * 130 * // Building a tag from a field number and a wire type. 131 * int tag = (fieldNumber << 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