1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <fcntl.h>
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <malloc.h>
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "HeapInternal.h"
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "HeapSource.h"
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Float12.h"
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmGetHeapDebugInfo(HeapDebugInfoType info)
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (info) {
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kVirtualHeapSize:
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (int)dvmHeapSourceGetValue(HS_FOOTPRINT, NULL, 0);
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kVirtualHeapAllocated:
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (int)dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, NULL, 0);
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Looks up the cmdline for the process and tries to find
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the most descriptive five characters, then inserts the
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * short name into the provided event value.
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define PROC_NAME_LEN 5
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void insertProcessName(long long *ep)
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static bool foundRealName = false;
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static char name[PROC_NAME_LEN] = { 'X', 'X', 'X', 'X', 'X' };
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    long long event = *ep;
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!foundRealName) {
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int fd = open("/proc/self/cmdline", O_RDONLY);
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (fd > 0) {
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char buf[128];
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ssize_t n = read(fd, buf, sizeof(buf) - 1);
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            close(fd);
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (n > 0) {
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                memset(name, 0, sizeof(name));
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (n <= PROC_NAME_LEN) {
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // The whole name fits.
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    memcpy(name, buf, n);
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* We need to truncate.  The name will look something
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * like "com.android.home".  Favor the characters
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * immediately following the last dot.
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    buf[n] = '\0';
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    char *dot = strrchr(buf, '.');
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (dot == NULL) {
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        /* Or, look for a slash, in case it's something like
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * "/system/bin/runtime".
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         */
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        dot = strrchr(buf, '/');
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (dot != NULL) {
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        dot++;  // Skip the dot
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        size_t dotlen = strlen(dot);
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        if (dotlen < PROC_NAME_LEN) {
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            /* Use all available characters.  We know that
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                             * n > PROC_NAME_LEN from the check above.
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                             */
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            dot -= PROC_NAME_LEN - dotlen;
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        strncpy(name, dot, PROC_NAME_LEN);
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        // No dot; just use the leading characters.
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        memcpy(name, buf, PROC_NAME_LEN);
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (strcmp(buf, "zygote") != 0) {
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* If the process is no longer called "zygote",
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * cache this name.
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    foundRealName = true;
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    event &= ~(0xffffffffffLL << 24);
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    event |= (long long)name[0] << 56;
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    event |= (long long)name[1] << 48;
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    event |= (long long)name[2] << 40;
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    event |= (long long)name[3] << 32;
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    event |= (long long)name[4] << 24;
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *ep = event;
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// See device/data/etc/event-log-tags
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define EVENT_LOG_TAG_dvm_gc_info 20001
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define EVENT_LOG_TAG_dvm_gc_madvise_info 20002
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLogGcStats(size_t numFreed, size_t sizeFreed, size_t gcTimeMs)
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const GcHeap *gcHeap = gDvm.gcHeap;
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t perHeapActualSize[HEAP_SOURCE_MAX_HEAP_COUNT],
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project           perHeapAllowedSize[HEAP_SOURCE_MAX_HEAP_COUNT],
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project           perHeapNumAllocated[HEAP_SOURCE_MAX_HEAP_COUNT],
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project           perHeapSizeAllocated[HEAP_SOURCE_MAX_HEAP_COUNT];
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned char eventBuf[1 + (1 + sizeof(long long)) * 4];
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t actualSize, allowedSize, numAllocated, sizeAllocated;
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t i;
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t softLimit = dvmHeapSourceGetIdealFootprint();
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t nHeaps = dvmHeapSourceGetNumHeaps();
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Enough to quiet down gcc for unitialized variable check */
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    perHeapActualSize[0] = perHeapAllowedSize[0] = perHeapNumAllocated[0] =
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                           perHeapSizeAllocated[0] = 0;
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    actualSize = dvmHeapSourceGetValue(HS_FOOTPRINT, perHeapActualSize,
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                       HEAP_SOURCE_MAX_HEAP_COUNT);
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    allowedSize = dvmHeapSourceGetValue(HS_ALLOWED_FOOTPRINT,
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                      perHeapAllowedSize, HEAP_SOURCE_MAX_HEAP_COUNT);
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    numAllocated = dvmHeapSourceGetValue(HS_OBJECTS_ALLOCATED,
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                      perHeapNumAllocated, HEAP_SOURCE_MAX_HEAP_COUNT);
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sizeAllocated = dvmHeapSourceGetValue(HS_BYTES_ALLOCATED,
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                      perHeapSizeAllocated, HEAP_SOURCE_MAX_HEAP_COUNT);
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Construct the the first 64-bit value to write to the log.
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Global information:
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [63   ] Must be zero
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [62-24] ASCII process identifier
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [23-12] GC time in ms
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [11- 0] Bytes freed
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    long long event0;
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    event0 = 0LL << 63 |
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(gcTimeMs) << 12 |
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(sizeFreed);
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    insertProcessName(&event0);
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Aggregated heap stats:
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [63-62] 10
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [61-60] Reserved; must be zero
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [59-48] Objects freed
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [47-36] Actual size (current footprint)
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [35-24] Allowed size (current hard max)
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [23-12] Objects allocated
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [11- 0] Bytes allocated
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    long long event1;
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    event1 = 2LL << 62 |
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(numFreed) << 48 |
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(actualSize) << 36 |
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(allowedSize) << 24 |
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(numAllocated) << 12 |
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(sizeAllocated);
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Report the current state of the zygote heap(s).
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The active heap is always heap[0].  We can be in one of three states
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * at present:
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  (1) Still in the zygote.  Zygote using heap[0].
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  (2) In the zygote, when the first child is started.  We created a
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *      new heap just before the first fork() call, so the original
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *      "zygote heap" is now heap[1], and we have a small heap[0] for
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *      anything we do from here on.
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  (3) In an app process.  The app gets a new heap[0], and can also
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *      see the two zygote heaps [1] and [2] (probably unwise to
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *      assume any specific ordering).
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * So if nHeaps == 1, we want the stats from heap[0]; else we want
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the sum of the values from heap[1] to heap[nHeaps-1].
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Zygote heap stats (except for the soft limit, which belongs to the
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * active heap):
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [63-62] 11
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [61-60] Reserved; must be zero
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [59-48] Soft Limit (for the active heap)
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [47-36] Actual size (current footprint)
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [35-24] Allowed size (current hard max)
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [23-12] Objects allocated
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [11- 0] Bytes allocated
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    long long event2;
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t zActualSize, zAllowedSize, zNumAllocated, zSizeAllocated;
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int firstHeap = (nHeaps == 1) ? 0 : 1;
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t hh;
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    zActualSize = zAllowedSize = zNumAllocated = zSizeAllocated = 0;
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (hh = firstHeap; hh < nHeaps; hh++) {
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        zActualSize += perHeapActualSize[hh];
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        zAllowedSize += perHeapAllowedSize[hh];
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        zNumAllocated += perHeapNumAllocated[hh];
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        zSizeAllocated += perHeapSizeAllocated[hh];
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    event2 = 3LL << 62 |
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(softLimit) << 48 |
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(zActualSize) << 36 |
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(zAllowedSize) << 24 |
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(zNumAllocated) << 12 |
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(zSizeAllocated);
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Report the current external allocation stats and the native heap
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * summary.
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [63-48] Reserved; must be zero (TODO: put new data in these slots)
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [47-36] dlmalloc_footprint
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [35-24] mallinfo: total allocated space
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [23-12] External byte limit
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [11- 0] External bytes allocated
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    long long event3;
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t externalLimit, externalBytesAllocated;
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t uordblks, footprint;
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This adds 2-5msec to the GC cost on a DVT, or about 2-3% of the cost
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of a GC, so it's not horribly expensive but it's not free either.
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    extern size_t dlmalloc_footprint(void);
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct mallinfo mi;
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //u8 start, end;
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //start = dvmGetRelativeTimeNsec();
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mi = mallinfo();
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uordblks = mi.uordblks;
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    footprint = dlmalloc_footprint();
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //end = dvmGetRelativeTimeNsec();
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGD("mallinfo+footprint took %dusec; used=%zd footprint=%zd\n",
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //    (int)((end - start) / 1000), mi.uordblks, footprint);
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uordblks = footprint = 0;
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    externalLimit =
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmHeapSourceGetValue(HS_EXTERNAL_LIMIT, NULL, 0);
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    externalBytesAllocated =
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmHeapSourceGetValue(HS_EXTERNAL_BYTES_ALLOCATED, NULL, 0);
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    event3 =
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(footprint) << 36 |
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(uordblks) << 24 |
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(externalLimit) << 12 |
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (long long)intToFloat12(externalBytesAllocated);
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Build the event data.
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [ 0: 0] item count (4)
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [ 1: 1] EVENT_TYPE_LONG
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [ 2: 9] event0
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [10:10] EVENT_TYPE_LONG
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [11:18] event1
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [19:19] EVENT_TYPE_LONG
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [20:27] event2
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [28:28] EVENT_TYPE_LONG
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [29:36] event2
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned char *c = eventBuf;
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *c++ = 4;
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *c++ = EVENT_TYPE_LONG;
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(c, &event0, sizeof(event0));
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    c += sizeof(event0);
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *c++ = EVENT_TYPE_LONG;
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(c, &event1, sizeof(event1));
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    c += sizeof(event1);
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *c++ = EVENT_TYPE_LONG;
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(c, &event2, sizeof(event2));
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    c += sizeof(event2);
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *c++ = EVENT_TYPE_LONG;
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(c, &event3, sizeof(event3));
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    (void) android_btWriteLog(EVENT_LOG_TAG_dvm_gc_info, EVENT_TYPE_LIST,
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            eventBuf, sizeof(eventBuf));
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLogMadviseStats(size_t madvisedSizes[], size_t arrayLen)
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned char eventBuf[1 + (1 + sizeof(int)) * 2];
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t total, zyg;
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t firstHeap, i;
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t nHeaps = dvmHeapSourceGetNumHeaps();
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(arrayLen >= nHeaps);
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    firstHeap = nHeaps > 1 ? 1 : 0;
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    total = 0;
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    zyg = 0;
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < nHeaps; i++) {
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        total += madvisedSizes[i];
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (i >= firstHeap) {
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            zyg += madvisedSizes[i];
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Build the event data.
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [ 0: 0] item count (2)
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [ 1: 1] EVENT_TYPE_INT
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [ 2: 5] total madvise byte count
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [ 6: 6] EVENT_TYPE_INT
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * [ 7:10] zygote heap madvise byte count
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned char *c = eventBuf;
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *c++ = 2;
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *c++ = EVENT_TYPE_INT;
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(c, &total, sizeof(total));
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    c += sizeof(total);
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *c++ = EVENT_TYPE_INT;
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(c, &zyg, sizeof(zyg));
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    c += sizeof(zyg);
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    (void) android_btWriteLog(EVENT_LOG_TAG_dvm_gc_madvise_info,
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            EVENT_TYPE_LIST, eventBuf, sizeof(eventBuf));
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h>
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdio.h>
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct HeapDumpContext {
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FILE *fp;
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void *chunkStart;
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t chunkLen;
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool chunkFree;
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} HeapDumpContext;
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectdump_context(const HeapDumpContext *ctx)
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(ctx->fp, "0x%08x %12.12zd %s\n", (uintptr_t)ctx->chunkStart,
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ctx->chunkLen, ctx->chunkFree ? "FREE" : "USED");
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectheap_chunk_callback(const void *chunkptr, size_t chunklen,
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    const void *userptr, size_t userlen, void *arg)
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HeapDumpContext *ctx = (HeapDumpContext *)arg;
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool chunkFree = (userptr == NULL);
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (chunkFree != ctx->chunkFree ||
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ((char *)ctx->chunkStart + ctx->chunkLen) != chunkptr)
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* The new chunk is of a different type or isn't
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * contiguous with the current chunk.  Dump the
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * old one and start a new one.
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ctx->chunkStart != NULL) {
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* It's not the first chunk. */
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dump_context(ctx);
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ctx->chunkStart = (void *)chunkptr;
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ctx->chunkLen = chunklen;
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ctx->chunkFree = chunkFree;
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Extend the current chunk.
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ctx->chunkLen += chunklen;
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Dumps free and used ranges, as text, to the named file.
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpHeapToFile(const char *fileName)
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HeapDumpContext ctx;
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FILE *fp;
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fp = fopen(fileName, "w+");
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (fp == NULL) {
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Can't open %s for writing: %s\n", fileName, strerror(errno));
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGW("Dumping heap to %s...\n", fileName);
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(fp, "==== Dalvik heap dump ====\n");
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(&ctx, 0, sizeof(ctx));
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx.fp = fp;
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHeapSourceWalk(heap_chunk_callback, (void *)&ctx);
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dump_context(&ctx);
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(fp, "==== end heap dump ====\n");
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGW("Dumped heap to %s.\n", fileName);
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fclose(fp);
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
404