blob: 89c9bb253524711c27c4129eb3f6a0837f586bbc [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
Chenjie Yu12e5e672018-09-14 15:54:59 -070018import android.util.Slog;
19
20import java.util.ArrayList;
21import java.util.List;
David Chen1481fe12017-10-16 13:16:34 -070022
23/**
24 * Wrapper class for sending data from Android OS to StatsD.
25 *
26 * @hide
27 */
28public final class StatsLogEventWrapper implements Parcelable {
Chenjie Yu12e5e672018-09-14 15:54:59 -070029 static final boolean DEBUG = false;
30 static final String TAG = "StatsLogEventWrapper";
David Chen1481fe12017-10-16 13:16:34 -070031
Chenjie Yu12e5e672018-09-14 15:54:59 -070032 // Keep in sync with FieldValue.h enums
33 private static final int EVENT_TYPE_UNKNOWN = 0;
34 private static final int EVENT_TYPE_INT = 1; /* int32_t */
35 private static final int EVENT_TYPE_LONG = 2; /* int64_t */
36 private static final int EVENT_TYPE_FLOAT = 3;
37 private static final int EVENT_TYPE_DOUBLE = 4;
38 private static final int EVENT_TYPE_STRING = 5;
39 private static final int EVENT_TYPE_STORAGE = 6;
David Chen1481fe12017-10-16 13:16:34 -070040
Chenjie Yu12e5e672018-09-14 15:54:59 -070041 List<Integer> mTypes = new ArrayList<>();
42 List<Object> mValues = new ArrayList<>();
43 int mTag;
44 long mElapsedTimeNs;
45 long mWallClockTimeNs;
Chenjie Yud7e3a222018-11-28 21:29:44 +000046 WorkSource mWorkSource = null;
Chenjie Yu12e5e672018-09-14 15:54:59 -070047
48 public StatsLogEventWrapper(int tag, long elapsedTimeNs, long wallClockTimeNs) {
49 this.mTag = tag;
50 this.mElapsedTimeNs = elapsedTimeNs;
51 this.mWallClockTimeNs = wallClockTimeNs;
David Chen1481fe12017-10-16 13:16:34 -070052 }
53
54 /**
55 * Boilerplate for Parcel.
56 */
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -070057 public static final @android.annotation.NonNull Parcelable.Creator<StatsLogEventWrapper> CREATOR = new
David Chen1481fe12017-10-16 13:16:34 -070058 Parcelable.Creator<StatsLogEventWrapper>() {
59 public StatsLogEventWrapper createFromParcel(Parcel in) {
Tej Singha0c89dd2019-01-25 16:39:18 -080060 return new StatsLogEventWrapper(in);
David Chen1481fe12017-10-16 13:16:34 -070061 }
62
63 public StatsLogEventWrapper[] newArray(int size) {
Tej Singha0c89dd2019-01-25 16:39:18 -080064 return new StatsLogEventWrapper[size];
David Chen1481fe12017-10-16 13:16:34 -070065 }
66 };
67
Tej Singha0c89dd2019-01-25 16:39:18 -080068 private StatsLogEventWrapper(Parcel in) {
69 readFromParcel(in);
70 }
71
Chenjie Yuab530202018-09-26 12:39:20 -070072 /**
Chenjie Yud7e3a222018-11-28 21:29:44 +000073 * Set work source if any.
74 */
75 public void setWorkSource(WorkSource ws) {
76 if (ws.getWorkChains() == null || ws.getWorkChains().size() == 0) {
77 Slog.w(TAG, "Empty worksource!");
78 return;
79 }
80 mWorkSource = ws;
81 }
82
83 /**
Chenjie Yuab530202018-09-26 12:39:20 -070084 * Write a int value.
85 */
David Chen1481fe12017-10-16 13:16:34 -070086 public void writeInt(int val) {
Chenjie Yu12e5e672018-09-14 15:54:59 -070087 mTypes.add(EVENT_TYPE_INT);
88 mValues.add(val);
David Chen1481fe12017-10-16 13:16:34 -070089 }
90
Chenjie Yuab530202018-09-26 12:39:20 -070091 /**
92 * Write a long value.
93 */
David Chen1481fe12017-10-16 13:16:34 -070094 public void writeLong(long val) {
Chenjie Yu12e5e672018-09-14 15:54:59 -070095 mTypes.add(EVENT_TYPE_LONG);
96 mValues.add(val);
David Chen1481fe12017-10-16 13:16:34 -070097 }
98
99 /**
Chenjie Yu12e5e672018-09-14 15:54:59 -0700100 * Write a string value.
David Chen1481fe12017-10-16 13:16:34 -0700101 */
102 public void writeString(String val) {
Chenjie Yu12e5e672018-09-14 15:54:59 -0700103 mTypes.add(EVENT_TYPE_STRING);
104 // use empty string for null
105 mValues.add(val == null ? "" : val);
106 }
107
Chenjie Yuab530202018-09-26 12:39:20 -0700108 /**
109 * Write a float value.
110 */
Chenjie Yu12e5e672018-09-14 15:54:59 -0700111 public void writeFloat(float val) {
112 mTypes.add(EVENT_TYPE_FLOAT);
113 mValues.add(val);
David Chen1481fe12017-10-16 13:16:34 -0700114 }
115
David Chen1481fe12017-10-16 13:16:34 -0700116 /**
Chenjie Yu12e5e672018-09-14 15:54:59 -0700117 * Write a storage value.
Tej Singh86dc9db2018-09-06 00:39:57 +0000118 */
Chenjie Yu12e5e672018-09-14 15:54:59 -0700119 public void writeStorage(byte[] val) {
120 mTypes.add(EVENT_TYPE_STORAGE);
121 mValues.add(val);
122 }
123
Chenjie Yuab530202018-09-26 12:39:20 -0700124 /**
125 * Write a boolean value.
126 */
Tej Singh86dc9db2018-09-06 00:39:57 +0000127 public void writeBoolean(boolean val) {
Chenjie Yu12e5e672018-09-14 15:54:59 -0700128 mTypes.add(EVENT_TYPE_INT);
129 mValues.add(val ? 1 : 0);
Tej Singh86dc9db2018-09-06 00:39:57 +0000130 }
131
David Chen1481fe12017-10-16 13:16:34 -0700132 public void writeToParcel(Parcel out, int flags) {
Chenjie Yu12e5e672018-09-14 15:54:59 -0700133 if (DEBUG) {
134 Slog.d(TAG,
135 "Writing " + mTag + " " + mElapsedTimeNs + " " + mWallClockTimeNs + " and "
136 + mTypes.size() + " elements.");
137 }
138 out.writeInt(mTag);
139 out.writeLong(mElapsedTimeNs);
140 out.writeLong(mWallClockTimeNs);
Chenjie Yud7e3a222018-11-28 21:29:44 +0000141 if (mWorkSource != null) {
142 ArrayList<android.os.WorkSource.WorkChain> workChains = mWorkSource.getWorkChains();
143 // number of chains
144 out.writeInt(workChains.size());
145 for (int i = 0; i < workChains.size(); i++) {
146 android.os.WorkSource.WorkChain wc = workChains.get(i);
147 if (wc.getSize() == 0) {
148 Slog.w(TAG, "Empty work chain.");
149 out.writeInt(0);
150 continue;
151 }
152 if (wc.getUids().length != wc.getTags().length
153 || wc.getUids().length != wc.getSize()) {
154 Slog.w(TAG, "Malformated work chain.");
155 out.writeInt(0);
156 continue;
157 }
158 // number of nodes
159 out.writeInt(wc.getSize());
160 for (int j = 0; j < wc.getSize(); j++) {
161 out.writeInt(wc.getUids()[j]);
162 out.writeString(wc.getTags()[j] == null ? "" : wc.getTags()[j]);
163 }
164 }
165 } else {
166 // no chains
167 out.writeInt(0);
168 }
Chenjie Yu12e5e672018-09-14 15:54:59 -0700169 out.writeInt(mTypes.size());
170 for (int i = 0; i < mTypes.size(); i++) {
171 out.writeInt(mTypes.get(i));
172 switch (mTypes.get(i)) {
173 case EVENT_TYPE_INT:
174 out.writeInt((int) mValues.get(i));
175 break;
176 case EVENT_TYPE_LONG:
177 out.writeLong((long) mValues.get(i));
178 break;
179 case EVENT_TYPE_FLOAT:
180 out.writeFloat((float) mValues.get(i));
181 break;
Chenjie Yuab530202018-09-26 12:39:20 -0700182 case EVENT_TYPE_DOUBLE:
183 out.writeDouble((double) mValues.get(i));
184 break;
Chenjie Yu12e5e672018-09-14 15:54:59 -0700185 case EVENT_TYPE_STRING:
186 out.writeString((String) mValues.get(i));
187 break;
188 case EVENT_TYPE_STORAGE:
189 out.writeByteArray((byte[]) mValues.get(i));
190 break;
191 default:
192 break;
193 }
194 }
David Chen1481fe12017-10-16 13:16:34 -0700195 }
196
197 /**
Tej Singha0c89dd2019-01-25 16:39:18 -0800198 * Reads from parcel and appropriately fills member fields.
199 */
200 public void readFromParcel(Parcel in) {
201 mTypes = new ArrayList<>();
202 mValues = new ArrayList<>();
203 mWorkSource = null;
204
205 mTag = in.readInt();
206 mElapsedTimeNs = in.readLong();
207 mWallClockTimeNs = in.readLong();
208
209 // Clear any data.
210 if (DEBUG) {
211 Slog.d(TAG, "Reading " + mTag + " " + mElapsedTimeNs + " " + mWallClockTimeNs);
212 }
213 // Set up worksource if present.
214 int numWorkChains = in.readInt();
215 if (numWorkChains > 0) {
216 mWorkSource = new WorkSource();
217 for (int i = 0; i < numWorkChains; i++) {
218 android.os.WorkSource.WorkChain workChain = mWorkSource.createWorkChain();
219 int workChainSize = in.readInt();
220 for (int j = 0; j < workChainSize; j++) {
221 int uid = in.readInt();
222 String tag = in.readString();
223 workChain.addNode(uid, tag);
224 }
225 }
226 }
227
228 // Do the rest of the types.
229 int numTypes = in.readInt();
230 if (DEBUG) {
231 Slog.d(TAG, "Reading " + numTypes + " elements");
232 }
233 for (int i = 0; i < numTypes; i++) {
234 int type = in.readInt();
235 mTypes.add(type);
236 switch (type) {
237 case EVENT_TYPE_INT:
238 mValues.add(in.readInt());
239 break;
240 case EVENT_TYPE_LONG:
241 mValues.add(in.readLong());
242 break;
243 case EVENT_TYPE_FLOAT:
244 mValues.add(in.readFloat());
245 break;
246 case EVENT_TYPE_DOUBLE:
247 mValues.add(in.readDouble());
248 break;
249 case EVENT_TYPE_STRING:
250 mValues.add(in.readString());
251 break;
252 case EVENT_TYPE_STORAGE:
253 mValues.add(in.createByteArray());
254 break;
255 default:
256 break;
257 }
258 }
259 }
260
261 /**
David Chen1481fe12017-10-16 13:16:34 -0700262 * Boilerplate for Parcel.
263 */
264 public int describeContents() {
265 return 0;
266 }
267}