Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f3d9908a authored by Andy Hung's avatar Andy Hung Committed by Android (Google) Code Review
Browse files

Merge "Add memory heap checks for mediaserver and audioserver" into nyc-dev

parents b2379ba0 07b745e1
Loading
Loading
Loading
Loading
+6 −2
Original line number Original line Diff line number Diff line
@@ -337,7 +337,7 @@ ssize_t DrmManagerService::pread(int uniqueId, DecryptHandle* decryptHandle,
    return mDrmManager->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
    return mDrmManager->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
}
}


status_t DrmManagerService::dump(int fd, const Vector<String16>& /* args */)
status_t DrmManagerService::dump(int fd, const Vector<String16>& args)
{
{
    const size_t SIZE = 256;
    const size_t SIZE = 256;
    char buffer[SIZE];
    char buffer[SIZE];
@@ -357,8 +357,12 @@ status_t DrmManagerService::dump(int fd, const Vector<String16>& /* args */)
            }
            }
        }
        }
        if (dumpMem) {
        if (dumpMem) {
            dumpMemoryAddresses(fd);
            result.append("\nDumping memory:\n");
            std::string s = dumpMemoryAddresses(100 /* limit */);
            result.append(s.c_str(), s.size());
        }
        }
#else
        (void)args;
#endif
#endif
    }
    }
    write(fd, result.string(), result.size());
    write(fd, result.string(), result.size());
+7 −2
Original line number Original line Diff line number Diff line
@@ -16,11 +16,16 @@
#ifndef MEMORY_LEAK_TRACK_UTIL_H
#ifndef MEMORY_LEAK_TRACK_UTIL_H
#define MEMORY_LEAK_TRACK_UTIL_H
#define MEMORY_LEAK_TRACK_UTIL_H


#include <iostream>

namespace android {
namespace android {
/*
/*
 * Dump the memory address of the calling process to the given fd.
 * Dump the heap memory of the calling process, sorted by total size
 * (allocation size * number of allocations).
 *
 *    limit is the number of unique allocations to return.
 */
 */
extern void dumpMemoryAddresses(int fd);
extern std::string dumpMemoryAddresses(size_t limit);


};
};


+3 −0
Original line number Original line Diff line number Diff line
@@ -81,6 +81,9 @@ LOCAL_SHARED_LIBRARIES := \


LOCAL_WHOLE_STATIC_LIBRARIES := libmedia_helper
LOCAL_WHOLE_STATIC_LIBRARIES := libmedia_helper


# for memory heap analysis
LOCAL_STATIC_LIBRARIES := libc_malloc_debug_backtrace libc_logging

LOCAL_MODULE:= libmedia
LOCAL_MODULE:= libmedia


LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+62 −144
Original line number Original line Diff line number Diff line
@@ -14,166 +14,84 @@
 * limitations under the License.
 * limitations under the License.
 */
 */


#include <media/MemoryLeakTrackUtil.h>


#include <stdio.h>
//#define LOG_NDEBUG 0
#include <stdlib.h>
#define LOG_TAG "MemoryLeackTrackUtil"
#include <string.h>
#include <utils/Log.h>
#include <sys/types.h>

#include <unistd.h>
#include "media/MemoryLeakTrackUtil.h"
#include <sstream>


/*
/*
 * The code here originally resided in MediaPlayerService.cpp and was
 * The code here originally resided in MediaPlayerService.cpp
 * shamelessly copied over to support memory leak tracking from
 * multiple places.
 */
 */
namespace android {


// Figure out the abi based on defined macros.
#if defined(__arm__)
#if defined(__arm__)
#define ABI_STRING "arm"
#elif defined(__aarch64__)
#define ABI_STRING "arm64"
#elif defined(__mips__) && !defined(__LP64__)
#define ABI_STRING "mips"
#elif defined(__mips__) && defined(__LP64__)
#define ABI_STRING "mips64"
#elif defined(__i386__)
#define ABI_STRING "x86"
#elif defined(__x86_64__)
#define ABI_STRING "x86_64"
#else
#error "Unsupported ABI"
#endif

extern std::string backtrace_string(const uintptr_t* frames, size_t frame_count);

namespace android {


extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
        size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
        size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);


extern "C" void free_malloc_leak_info(uint8_t* info);
extern "C" void free_malloc_leak_info(uint8_t* info);


// Use the String-class below instead of String8 to allocate all memory
std::string dumpMemoryAddresses(size_t limit)
// beforehand and not reenter the heap while we are examining it...
struct MyString8 {
    static const size_t MAX_SIZE = 256 * 1024;

    MyString8()
        : mPtr((char *)malloc(MAX_SIZE)) {
        *mPtr = '\0';
    }

    ~MyString8() {
        free(mPtr);
    }

    void append(const char *s) {
        strncat(mPtr, s, MAX_SIZE - size() - 1);
    }

    const char *string() const {
        return mPtr;
    }

    size_t size() const {
        return strlen(mPtr);
    }

    void clear() {
        *mPtr = '\0';
    }

private:
    char *mPtr;

    MyString8(const MyString8 &);
    MyString8 &operator=(const MyString8 &);
};

void dumpMemoryAddresses(int fd)
{
{
    const size_t SIZE = 256;
    uint8_t *info;
    char buffer[SIZE];
    size_t overallSize;
    MyString8 result;
    size_t infoSize;

    size_t totalMemory;
    typedef struct {
    size_t backtraceSize;
        size_t size;
        size_t dups;
        intptr_t * backtrace;
    } AllocEntry;

    uint8_t *info = NULL;
    size_t overallSize = 0;
    size_t infoSize = 0;
    size_t totalMemory = 0;
    size_t backtraceSize = 0;

    get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
    get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
    if (info) {
        uint8_t *ptr = info;
        size_t count = overallSize / infoSize;

        snprintf(buffer, SIZE, " Allocation count %i\n", count);
        result.append(buffer);
        snprintf(buffer, SIZE, " Total memory %i\n", totalMemory);
        result.append(buffer);

        AllocEntry * entries = new AllocEntry[count];

        for (size_t i = 0; i < count; i++) {
            // Each entry should be size_t, size_t, intptr_t[backtraceSize]
            AllocEntry *e = &entries[i];


            e->size = *reinterpret_cast<size_t *>(ptr);
    size_t count;
            ptr += sizeof(size_t);
    if (info == nullptr || overallSize == 0 || infoSize == 0

            || (count = overallSize / infoSize) == 0) {
            e->dups = *reinterpret_cast<size_t *>(ptr);
        ALOGD("no malloc info, libc.debug.malloc.program property should be set");
            ptr += sizeof(size_t);
        return std::string();

            e->backtrace = reinterpret_cast<intptr_t *>(ptr);
            ptr += sizeof(intptr_t) * backtraceSize;
        }

        // Now we need to sort the entries.  They come sorted by size but
        // not by stack trace which causes problems using diff.
        bool moved;
        do {
            moved = false;
            for (size_t i = 0; i < (count - 1); i++) {
                AllocEntry *e1 = &entries[i];
                AllocEntry *e2 = &entries[i+1];

                bool swap = e1->size < e2->size;
                if (e1->size == e2->size) {
                    for(size_t j = 0; j < backtraceSize; j++) {
                        if (e1->backtrace[j] == e2->backtrace[j]) {
                            continue;
                        }
                        swap = e1->backtrace[j] < e2->backtrace[j];
                        break;
    }
    }
                }
                if (swap) {
                    AllocEntry t = entries[i];
                    entries[i] = entries[i+1];
                    entries[i+1] = t;
                    moved = true;
                }
            }
        } while (moved);


        write(fd, result.string(), result.size());
    std::ostringstream oss;
        result.clear();
    oss << totalMemory << " bytes in " << count << " allocations\n";
    oss << "  ABI: '" ABI_STRING "'" << "\n\n";
    if (count > limit) count = limit;


    // The memory is sorted based on total size which is useful for finding
    // worst memory offenders. For diffs, sometimes it is preferable to sort
    // based on the backtrace.
    for (size_t i = 0; i < count; i++) {
    for (size_t i = 0; i < count; i++) {
            AllocEntry *e = &entries[i];
        struct AllocEntry {
            size_t size;  // bit 31 is set if this is zygote allocated memory
            size_t allocations;
            uintptr_t backtrace[];
        };


            snprintf(buffer, SIZE, "size %8i, dup %4i, ", e->size, e->dups);
        const AllocEntry * const e = (AllocEntry *)(info + i * infoSize);
            result.append(buffer);
            for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) {
                if (ct) {
                    result.append(", ");
                }
                snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]);
                result.append(buffer);
            }
            result.append("\n");


            write(fd, result.string(), result.size());
        oss << (e->size * e->allocations)
            result.clear();
                << " bytes ( " << e->size << " bytes * " << e->allocations << " allocations )\n";
        oss << backtrace_string(e->backtrace, backtraceSize) << "\n";
    }
    }

    oss << "\n";
        delete[] entries;
    free_malloc_leak_info(info);
    free_malloc_leak_info(info);
    }
    return oss.str();
}
}


#else
// Does nothing
void dumpMemoryAddresses(int fd __unused) {}

#endif
}  // namespace android
}  // namespace android
+3 −1
Original line number Original line Diff line number Diff line
@@ -536,7 +536,9 @@ status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
            }
            }
        }
        }
        if (dumpMem) {
        if (dumpMem) {
            dumpMemoryAddresses(fd);
            result.append("\nDumping memory:\n");
            std::string s = dumpMemoryAddresses(100 /* limit */);
            result.append(s.c_str(), s.size());
        }
        }
        if (unreachableMemory) {
        if (unreachableMemory) {
            result.append("\nDumping unreachable memory:\n");
            result.append("\nDumping unreachable memory:\n");
Loading