2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.ddmlib.log;
19 import com.android.ddmlib.log.EventValueDescription.ValueType;
20 import com.android.ddmlib.log.LogReceiver.LogEntry;
23 * Custom Event Container for the Gc event since this event doesn't simply output data in
24 * int or long format, but encodes several values on 4 longs.
26 * The array of {@link EventValueDescription}s parsed from the "event-log-tags" file must
27 * be ignored, and instead, the array returned from {@link #getValueDescriptions()} must be used.
29 final class GcEventContainer extends EventContainer {
31 public final static int GC_EVENT_TAG = 20001;
33 private String processId;
35 private long bytesFreed;
36 private long objectsFreed;
37 private long actualSize;
38 private long allowedSize;
39 private long softLimit;
40 private long objectsAllocated;
41 private long bytesAllocated;
42 private long zActualSize;
43 private long zAllowedSize;
44 private long zObjectsAllocated;
45 private long zBytesAllocated;
46 private long dlmallocFootprint;
47 private long mallinfoTotalAllocatedSpace;
48 private long externalLimit;
49 private long externalBytesAllocated;
51 GcEventContainer(LogEntry entry, int tag, Object data) {
52 super(entry, tag, data);
56 GcEventContainer(int tag, int pid, int tid, int sec, int nsec, Object data) {
57 super(tag, pid, tid, sec, nsec, data);
64 private void init(Object data) {
65 if (data instanceof Object[]) {
66 Object[] values = (Object[])data;
67 for (int i = 0; i < values.length; i++) {
68 if (values[i] instanceof Long) {
69 parseDvmHeapInfo((Long)values[i], i);
76 public EventValueType getType() {
77 return EventValueType.LIST;
81 public boolean testValue(int index, Object value, CompareMethod compareMethod)
82 throws InvalidTypeException {
83 // do a quick easy check on the type.
85 if ((value instanceof String) == false) {
86 throw new InvalidTypeException();
88 } else if ((value instanceof Long) == false) {
89 throw new InvalidTypeException();
92 switch (compareMethod) {
95 return processId.equals(value);
97 return getValueAsLong(index) == ((Long)value).longValue();
100 return getValueAsLong(index) <= ((Long)value).longValue();
101 case LESSER_THAN_STRICT:
102 return getValueAsLong(index) < ((Long)value).longValue();
104 return getValueAsLong(index) >= ((Long)value).longValue();
105 case GREATER_THAN_STRICT:
106 return getValueAsLong(index) > ((Long)value).longValue();
108 return (getValueAsLong(index) & ((Long)value).longValue()) != 0;
111 throw new ArrayIndexOutOfBoundsException();
115 public Object getValue(int valueIndex) {
116 if (valueIndex == 0) {
121 return new Long(getValueAsLong(valueIndex));
122 } catch (InvalidTypeException e) {
123 // this would only happened if valueIndex was 0, which we test above.
130 public double getValueAsDouble(int valueIndex) throws InvalidTypeException {
131 return (double)getValueAsLong(valueIndex);
135 public String getValueAsString(int valueIndex) {
136 switch (valueIndex) {
141 return Long.toString(getValueAsLong(valueIndex));
142 } catch (InvalidTypeException e) {
143 // we shouldn't stop there since we test, in this method first.
147 throw new ArrayIndexOutOfBoundsException();
151 * Returns a custom array of {@link EventValueDescription} since the actual content of this
152 * event (list of (long, long) does not match the values encoded into those longs.
154 static EventValueDescription[] getValueDescriptions() {
156 return new EventValueDescription[] {
157 new EventValueDescription("Process Name", EventValueType.STRING),
158 new EventValueDescription("GC Time", EventValueType.LONG,
159 ValueType.MILLISECONDS),
160 new EventValueDescription("Freed Objects", EventValueType.LONG,
162 new EventValueDescription("Freed Bytes", EventValueType.LONG, ValueType.BYTES),
163 new EventValueDescription("Soft Limit", EventValueType.LONG, ValueType.BYTES),
164 new EventValueDescription("Actual Size (aggregate)", EventValueType.LONG,
166 new EventValueDescription("Allowed Size (aggregate)", EventValueType.LONG,
168 new EventValueDescription("Allocated Objects (aggregate)",
169 EventValueType.LONG, ValueType.OBJECTS),
170 new EventValueDescription("Allocated Bytes (aggregate)", EventValueType.LONG,
172 new EventValueDescription("Actual Size", EventValueType.LONG, ValueType.BYTES),
173 new EventValueDescription("Allowed Size", EventValueType.LONG, ValueType.BYTES),
174 new EventValueDescription("Allocated Objects", EventValueType.LONG,
176 new EventValueDescription("Allocated Bytes", EventValueType.LONG,
178 new EventValueDescription("Actual Size (zygote)", EventValueType.LONG,
180 new EventValueDescription("Allowed Size (zygote)", EventValueType.LONG,
182 new EventValueDescription("Allocated Objects (zygote)", EventValueType.LONG,
184 new EventValueDescription("Allocated Bytes (zygote)", EventValueType.LONG,
186 new EventValueDescription("External Allocation Limit", EventValueType.LONG,
188 new EventValueDescription("External Bytes Allocated", EventValueType.LONG,
190 new EventValueDescription("dlmalloc Footprint", EventValueType.LONG,
192 new EventValueDescription("Malloc Info: Total Allocated Space",
193 EventValueType.LONG, ValueType.BYTES),
195 } catch (InvalidValueTypeException e) {
196 // this shouldn't happen since we control manual the EventValueType and the ValueType
197 // values. For development purpose, we assert if this happens.
201 // this shouldn't happen, but the compiler complains otherwise.
205 private void parseDvmHeapInfo(long data, int index) {
208 // [63 ] Must be zero
209 // [62-24] ASCII process identifier
210 // [23-12] GC time in ms
211 // [11- 0] Bytes freed
213 gcTime = float12ToInt((int)((data >> 12) & 0xFFFL));
214 bytesFreed = float12ToInt((int)(data & 0xFFFL));
216 // convert the long into an array, in the proper order so that we can convert the
217 // first 5 char into a string.
218 byte[] dataArray = new byte[8];
219 put64bitsToArray(data, dataArray, 0);
221 // get the name from the string
222 processId = new String(dataArray, 0, 5);
226 // [61-60] Reserved; must be zero
227 // [59-48] Objects freed
228 // [47-36] Actual size (current footprint)
229 // [35-24] Allowed size (current hard max)
230 // [23-12] Objects allocated
231 // [11- 0] Bytes allocated
232 objectsFreed = float12ToInt((int)((data >> 48) & 0xFFFL));
233 actualSize = float12ToInt((int)((data >> 36) & 0xFFFL));
234 allowedSize = float12ToInt((int)((data >> 24) & 0xFFFL));
235 objectsAllocated = float12ToInt((int)((data >> 12) & 0xFFFL));
236 bytesAllocated = float12ToInt((int)(data & 0xFFFL));
240 // [61-60] Reserved; must be zero
241 // [59-48] Soft limit (current soft max)
242 // [47-36] Actual size (current footprint)
243 // [35-24] Allowed size (current hard max)
244 // [23-12] Objects allocated
245 // [11- 0] Bytes allocated
246 softLimit = float12ToInt((int)((data >> 48) & 0xFFFL));
247 zActualSize = float12ToInt((int)((data >> 36) & 0xFFFL));
248 zAllowedSize = float12ToInt((int)((data >> 24) & 0xFFFL));
249 zObjectsAllocated = float12ToInt((int)((data >> 12) & 0xFFFL));
250 zBytesAllocated = float12ToInt((int)(data & 0xFFFL));
253 // [63-48] Reserved; must be zero
254 // [47-36] dlmallocFootprint
255 // [35-24] mallinfo: total allocated space
256 // [23-12] External byte limit
257 // [11- 0] External bytes allocated
258 dlmallocFootprint = float12ToInt((int)((data >> 36) & 0xFFFL));
259 mallinfoTotalAllocatedSpace = float12ToInt((int)((data >> 24) & 0xFFFL));
260 externalLimit = float12ToInt((int)((data >> 12) & 0xFFFL));
261 externalBytesAllocated = float12ToInt((int)(data & 0xFFFL));
269 * Converts a 12 bit float representation into an unsigned int (returned as a long)
272 private static long float12ToInt(int f12) {
273 return (f12 & 0x1FF) << ((f12 >>> 9) * 4);
277 * puts an unsigned value in an array.
278 * @param value The value to put.
279 * @param dest the destination array
280 * @param offset the offset in the array where to put the value.
281 * Array length must be at least offset + 8
283 private static void put64bitsToArray(long value, byte[] dest, int offset) {
284 dest[offset + 7] = (byte)(value & 0x00000000000000FFL);
285 dest[offset + 6] = (byte)((value & 0x000000000000FF00L) >> 8);
286 dest[offset + 5] = (byte)((value & 0x0000000000FF0000L) >> 16);
287 dest[offset + 4] = (byte)((value & 0x00000000FF000000L) >> 24);
288 dest[offset + 3] = (byte)((value & 0x000000FF00000000L) >> 32);
289 dest[offset + 2] = (byte)((value & 0x0000FF0000000000L) >> 40);
290 dest[offset + 1] = (byte)((value & 0x00FF000000000000L) >> 48);
291 dest[offset + 0] = (byte)((value & 0xFF00000000000000L) >> 56);
295 * Returns the long value of the <code>valueIndex</code>-th value.
296 * @param valueIndex the index of the value.
297 * @throws InvalidTypeException if index is 0 as it is a string value.
299 private final long getValueAsLong(int valueIndex) throws InvalidTypeException {
300 switch (valueIndex) {
302 throw new InvalidTypeException();
316 return objectsAllocated;
318 return bytesAllocated;
320 return actualSize - zActualSize;
322 return allowedSize - zAllowedSize;
324 return objectsAllocated - zObjectsAllocated;
326 return bytesAllocated - zBytesAllocated;
332 return zObjectsAllocated;
334 return zBytesAllocated;
336 return externalLimit;
338 return externalBytesAllocated;
340 return dlmallocFootprint;
342 return mallinfoTotalAllocatedSpace;
345 throw new ArrayIndexOutOfBoundsException();