1 /*
2  * Copyright (C) 2017 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.util.AggStats;
20 import android.util.Duration;
21 
22 import java.io.IOException;
23 import java.util.Arrays;
24 
25 /**
26  * This class contains a list of helper functions to write common proto in
27  * //frameworks/base/core/proto/android/base directory
28  * @hide
29  */
30 public class ProtoUtils {
31 
32     /**
33      * Dump AggStats to ProtoOutputStream
34      */
toAggStatsProto(ProtoOutputStream proto, long fieldId, long min, long average, long max, int meanKb, int maxKb)35     public static void toAggStatsProto(ProtoOutputStream proto, long fieldId,
36             long min, long average, long max, int meanKb, int maxKb) {
37         final long aggStatsToken = proto.start(fieldId);
38         proto.write(AggStats.MIN, min);
39         proto.write(AggStats.AVERAGE, average);
40         proto.write(AggStats.MAX, max);
41         proto.write(AggStats.MEAN_KB, meanKb);
42         proto.write(AggStats.MAX_KB, maxKb);
43         proto.end(aggStatsToken);
44     }
45 
46     /**
47      * Dump AggStats to ProtoOutputStream
48      */
toAggStatsProto(ProtoOutputStream proto, long fieldId, long min, long average, long max)49     public static void toAggStatsProto(ProtoOutputStream proto, long fieldId,
50             long min, long average, long max) {
51         toAggStatsProto(proto, fieldId, min, average, max, 0, 0);
52     }
53 
54     /**
55      * Dump Duration to ProtoOutputStream
56      */
toDuration(ProtoOutputStream proto, long fieldId, long startMs, long endMs)57     public static void toDuration(ProtoOutputStream proto, long fieldId, long startMs, long endMs) {
58         final long token = proto.start(fieldId);
59         proto.write(Duration.START_MS, startMs);
60         proto.write(Duration.END_MS, endMs);
61         proto.end(token);
62     }
63 
64     /**
65      * Helper function to write bit-wise flags to proto as repeated enums
66      */
writeBitWiseFlagsToProtoEnum(ProtoOutputStream proto, long fieldId, long flags, int[] origEnums, int[] protoEnums)67     public static void writeBitWiseFlagsToProtoEnum(ProtoOutputStream proto, long fieldId,
68             long flags, int[] origEnums, int[] protoEnums) {
69         if (protoEnums.length != origEnums.length) {
70             throw new IllegalArgumentException("The length of origEnums must match protoEnums");
71         }
72         int len = origEnums.length;
73         for (int i = 0; i < len; i++) {
74             // handle zero flag case.
75             if (origEnums[i] == 0 && flags == 0) {
76                 proto.write(fieldId, protoEnums[i]);
77                 return;
78             }
79             if ((flags & origEnums[i]) != 0) {
80                 proto.write(fieldId, protoEnums[i]);
81             }
82         }
83     }
84 
85     /**
86      * Provide debug data about the current field as a string
87      */
currentFieldToString(ProtoInputStream proto)88     public static String currentFieldToString(ProtoInputStream proto) throws IOException {
89         StringBuilder sb = new StringBuilder();
90 
91         final int fieldNumber = proto.getFieldNumber();
92         final int wireType = proto.getWireType();
93         long fieldConstant;
94 
95         sb.append("Offset : 0x").append(Integer.toHexString(proto.getOffset()));
96         sb.append("\nField Number : 0x").append(Integer.toHexString(proto.getFieldNumber()));
97         sb.append("\nWire Type : ");
98         switch (wireType) {
99             case ProtoStream.WIRE_TYPE_VARINT:
100                 fieldConstant = ProtoStream.makeFieldId(fieldNumber,
101                         ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_INT64);
102                 sb.append("varint\nField Value : 0x");
103                 sb.append(Long.toHexString(proto.readLong(fieldConstant)));
104                 break;
105             case ProtoStream.WIRE_TYPE_FIXED64:
106                 fieldConstant = ProtoStream.makeFieldId(fieldNumber,
107                         ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_FIXED64);
108                 sb.append("fixed64\nField Value : 0x");
109                 sb.append(Long.toHexString(proto.readLong(fieldConstant)));
110                 break;
111             case ProtoStream.WIRE_TYPE_LENGTH_DELIMITED:
112                 fieldConstant = ProtoStream.makeFieldId(fieldNumber,
113                         ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_BYTES);
114                 sb.append("length delimited\nField Bytes : ");
115                 sb.append(Arrays.toString(proto.readBytes(fieldConstant)));
116                 break;
117             case ProtoStream.WIRE_TYPE_START_GROUP:
118                 sb.append("start group");
119                 break;
120             case ProtoStream.WIRE_TYPE_END_GROUP:
121                 sb.append("end group");
122                 break;
123             case ProtoStream.WIRE_TYPE_FIXED32:
124                 fieldConstant = ProtoStream.makeFieldId(fieldNumber,
125                         ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_FIXED32);
126                 sb.append("fixed32\nField Value : 0x");
127                 sb.append(Integer.toHexString(proto.readInt(fieldConstant)));
128                 break;
129             default:
130                 sb.append("unknown(").append(proto.getWireType()).append(")");
131         }
132         return sb.toString();
133     }
134 }
135