blob: d4d3dc838d91d9359d47aac2e52b749d64c52d64 [file] [log] [blame]
David Chen1481fe12017-10-16 13:16:34 -07001/*
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 */
16package android.os;
17
18import java.io.ByteArrayOutputStream;
19import java.nio.charset.StandardCharsets;
20
21/**
22 * Wrapper class for sending data from Android OS to StatsD.
23 *
24 * @hide
25 */
26public final class StatsLogEventWrapper implements Parcelable {
27 private ByteArrayOutputStream mStorage = new ByteArrayOutputStream();
28
29 // Below are constants copied from log/log.h
30 private static final int EVENT_TYPE_INT = 0; /* int32_t */
31 private static final int EVENT_TYPE_LONG = 1; /* int64_t */
32 private static final int EVENT_TYPE_STRING = 2;
33 private static final int EVENT_TYPE_LIST = 3;
34 private static final int EVENT_TYPE_FLOAT = 4;
35
Chenjie Yu6842a8c2017-12-05 22:34:34 -080036 // Keep this in sync with system/core/logcat/event.logtags
37 private static final int STATS_BUFFER_TAG_ID = 1937006964;
David Chen1481fe12017-10-16 13:16:34 -070038 /**
39 * Creates a log_event that is binary-encoded as implemented in
40 * system/core/liblog/log_event_list.c; this allows us to use the same parsing logic in statsd
41 * for pushed and pulled data. The write* methods must be called in the same order as their
42 * field number. There is no checking that the correct number of write* methods is called.
43 * We also write an END_LIST character before beginning to write to parcel, but this END_LIST
44 * may be unnecessary.
45 *
46 * @param tag The integer representing the tag for this event.
47 * @param fields The number of fields specified in this event.
48 */
Yangster-macc552b352018-02-22 10:00:45 -080049 public StatsLogEventWrapper(long elapsedNanos, int tag, int fields) {
David Chen1481fe12017-10-16 13:16:34 -070050 // Write four bytes from tag, starting with least-significant bit.
Chenjie Yu6842a8c2017-12-05 22:34:34 -080051 // For pulled data, this tag number is not really used. We use the same tag number as
52 // pushed ones to be consistent.
53 write4Bytes(STATS_BUFFER_TAG_ID);
David Chen1481fe12017-10-16 13:16:34 -070054 mStorage.write(EVENT_TYPE_LIST); // This is required to start the log entry.
Yangster-macc552b352018-02-22 10:00:45 -080055 mStorage.write(fields + 2); // Indicate number of elements in this list. +1 for the tag
56 // The first element is the elapsed realtime.
57 writeLong(elapsedNanos);
58 // The second element is the real atom tag number
59 writeInt(tag);
David Chen1481fe12017-10-16 13:16:34 -070060 }
61
62 /**
63 * Boilerplate for Parcel.
64 */
65 public static final Parcelable.Creator<StatsLogEventWrapper> CREATOR = new
66 Parcelable.Creator<StatsLogEventWrapper>() {
67 public StatsLogEventWrapper createFromParcel(Parcel in) {
68 return new StatsLogEventWrapper(in);
69 }
70
71 public StatsLogEventWrapper[] newArray(int size) {
72 return new StatsLogEventWrapper[size];
73 }
74 };
75
76 private void write4Bytes(int val) {
77 mStorage.write(val);
78 mStorage.write(val >>> 8);
79 mStorage.write(val >>> 16);
80 mStorage.write(val >>> 24);
81 }
82
83 private void write8Bytes(long val) {
84 write4Bytes((int) (val & 0xFFFFFFFF)); // keep the lowe 32-bits
85 write4Bytes((int) (val >>> 32)); // Write the high 32-bits.
86 }
87
88 /**
89 * Adds 32-bit integer to output.
90 */
91 public void writeInt(int val) {
92 mStorage.write(EVENT_TYPE_INT);
93 write4Bytes(val);
94 }
95
96 /**
97 * Adds 64-bit long to output.
98 */
99 public void writeLong(long val) {
100 mStorage.write(EVENT_TYPE_LONG);
101 write8Bytes(val);
102 }
103
104 /**
105 * Adds a 4-byte floating point value to output.
106 */
107 public void writeFloat(float val) {
108 int v = Float.floatToIntBits(val);
109 mStorage.write(EVENT_TYPE_FLOAT);
110 write4Bytes(v);
111 }
112
113 /**
114 * Adds a string to the output.
115 */
116 public void writeString(String val) {
117 mStorage.write(EVENT_TYPE_STRING);
118 write4Bytes(val.length());
119 byte[] bytes = val.getBytes(StandardCharsets.UTF_8);
120 mStorage.write(bytes, 0, bytes.length);
121 }
122
123 private StatsLogEventWrapper(Parcel in) {
124 readFromParcel(in);
125 }
126
127 /**
128 * Writes the stored fields to a byte array. Will first write a new-line character to denote
129 * END_LIST before writing contents to byte array.
130 */
131 public void writeToParcel(Parcel out, int flags) {
132 mStorage.write(10); // new-line character is same as END_LIST
133 out.writeByteArray(mStorage.toByteArray());
134 }
135
136 /**
137 * Not implemented.
138 */
139 public void readFromParcel(Parcel in) {
140 // Not needed since this java class is for sending to statsd only.
141 }
142
143 /**
144 * Boilerplate for Parcel.
145 */
146 public int describeContents() {
147 return 0;
148 }
149}