diff options
| author | James Dong <jdong@google.com> | 2011-03-14 17:01:38 -0700 | 
|---|---|---|
| committer | James Dong <jdong@google.com> | 2011-03-14 18:48:19 -0700 | 
| commit | 8635b7b095fbf7ffc63d3ce791891a9116ace1f6 (patch) | |
| tree | 6c9bbe1d0cec53f0c83099f1028302a178928cb9 | |
| parent | 1b99cc90afffbda6013ebbb45d64f17b1d90b9f5 (diff) | |
| download | frameworks_av-8635b7b095fbf7ffc63d3ce791891a9116ace1f6.zip frameworks_av-8635b7b095fbf7ffc63d3ce791891a9116ace1f6.tar.gz frameworks_av-8635b7b095fbf7ffc63d3ce791891a9116ace1f6.tar.bz2  | |
Add memory leak tracking/debugging code to drm server
bug - 4099038
Change-Id: I6c048eaf3d7f34bc144b8daaa5fdef1ed474af66
| -rw-r--r-- | drm/drmserver/Android.mk | 1 | ||||
| -rw-r--r-- | drm/drmserver/DrmManagerService.cpp | 29 | ||||
| -rw-r--r-- | drm/libdrmframework/include/DrmManagerService.h | 2 | ||||
| -rw-r--r-- | include/media/MemoryLeakTrackUtil.h | 28 | ||||
| -rw-r--r-- | media/libmedia/Android.mk | 1 | ||||
| -rw-r--r-- | media/libmedia/MemoryLeakTrackUtil.cpp | 169 | ||||
| -rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.cpp | 138 | 
7 files changed, 232 insertions, 136 deletions
diff --git a/drm/drmserver/Android.mk b/drm/drmserver/Android.mk index 5df2ff8..b5ad147 100644 --- a/drm/drmserver/Android.mk +++ b/drm/drmserver/Android.mk @@ -23,6 +23,7 @@ LOCAL_SRC_FILES:= \      StringTokenizer.cpp  LOCAL_SHARED_LIBRARIES := \ +    libmedia \      libutils \      libbinder diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp index 0901a44..583669e 100644 --- a/drm/drmserver/DrmManagerService.cpp +++ b/drm/drmserver/DrmManagerService.cpp @@ -19,6 +19,7 @@  #include <utils/Log.h>  #include <private/android_filesystem_config.h> +#include <media/MemoryLeakTrackUtil.h>  #include <errno.h>  #include <utils/threads.h> @@ -256,3 +257,31 @@ ssize_t DrmManagerService::pread(int uniqueId, DecryptHandle* decryptHandle,      return mDrmManager->pread(uniqueId, decryptHandle, buffer, numBytes, offset);  } +status_t DrmManagerService::dump(int fd, const Vector<String16>& args) +{ +    const size_t SIZE = 256; +    char buffer[SIZE]; +    String8 result; +    if (checkCallingPermission(String16("android.permission.DUMP")) == false) { +        snprintf(buffer, SIZE, "Permission Denial: " +                "can't dump DrmManagerService from pid=%d, uid=%d\n", +                IPCThreadState::self()->getCallingPid(), +                IPCThreadState::self()->getCallingUid()); +        result.append(buffer); +    } else { +#if DRM_MEMORY_LEAK_TRACK +        bool dumpMem = false; +        for (size_t i = 0; i < args.size(); i++) { +            if (args[i] == String16("-m")) { +                dumpMem = true; +            } +        } +        if (dumpMem) { +            dumpMemoryAddresses(fd); +        } +#endif +    } +    write(fd, result.string(), result.size()); +    return NO_ERROR; +} + diff --git a/drm/libdrmframework/include/DrmManagerService.h b/drm/libdrmframework/include/DrmManagerService.h index d0a0db7..227496a 100644 --- a/drm/libdrmframework/include/DrmManagerService.h +++ b/drm/libdrmframework/include/DrmManagerService.h @@ -115,6 +115,8 @@ public:      ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,              void* buffer, ssize_t numBytes, off64_t offset); +    virtual status_t dump(int fd, const Vector<String16>& args); +  private:      DrmManager* mDrmManager;  }; diff --git a/include/media/MemoryLeakTrackUtil.h b/include/media/MemoryLeakTrackUtil.h new file mode 100644 index 0000000..290b748 --- /dev/null +++ b/include/media/MemoryLeakTrackUtil.h @@ -0,0 +1,28 @@ + +/* + * Copyright 2011, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MEMORY_LEAK_TRACK_UTIL_H +#define MEMORY_LEAK_TRACK_UTIL_H + +namespace android { +/* + * Dump the memory adddress of the calling process to the given fd. + */ +extern void dumpMemoryAddresses(int fd); + +}; + +#endif  // MEMORY_LEAK_TRACK_UTIL_H diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index fd4c6c6..a04fbd2 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -33,6 +33,7 @@ LOCAL_SRC_FILES:= \      IEffectClient.cpp \      AudioEffect.cpp \      Visualizer.cpp \ +    MemoryLeakTrackUtil.cpp \      fixedfft.cpp.arm  LOCAL_SHARED_LIBRARIES := \ diff --git a/media/libmedia/MemoryLeakTrackUtil.cpp b/media/libmedia/MemoryLeakTrackUtil.cpp new file mode 100644 index 0000000..6a108ae --- /dev/null +++ b/media/libmedia/MemoryLeakTrackUtil.cpp @@ -0,0 +1,169 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <media/MemoryLeakTrackUtil.h> + +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> + +/* + * The code here originally resided in MediaPlayerService.cpp and was + * shamelessly copied over to support memory leak tracking from + * multiple places. + */ +namespace android { + +#if defined(__arm__) + +extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, +        size_t* infoSize, size_t* totalMemory, size_t* backtraceSize); + +extern "C" void free_malloc_leak_info(uint8_t* info); + +// Use the String-class below instead of String8 to allocate all memory +// 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) { +        strcat(mPtr, s); +    } + +    const char *string() const { +        return mPtr; +    } + +    size_t size() const { +        return strlen(mPtr); +    } + +private: +    char *mPtr; + +    MyString8(const MyString8 &); +    MyString8 &operator=(const MyString8 &); +}; + +void dumpMemoryAddresses(int fd) +{ +    const size_t SIZE = 256; +    char buffer[SIZE]; +    MyString8 result; + +    typedef struct { +        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); +    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); +            ptr += sizeof(size_t); + +            e->dups = *reinterpret_cast<size_t *>(ptr); +            ptr += sizeof(size_t); + +            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); + +        for (size_t i = 0; i < count; i++) { +            AllocEntry *e = &entries[i]; + +            snprintf(buffer, SIZE, "size %8i, dup %4i, ", e->size, e->dups); +            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"); +        } + +        delete[] entries; +        free_malloc_leak_info(info); +    } + +    write(fd, result.string(), result.size()); +} + +#else +// Does nothing +void dumpMemoryAddresses(int fd) {} + +#endif +}  // namespace android diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index a42cca5..f075706 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -51,6 +51,7 @@  #include <media/MediaMetadataRetrieverInterface.h>  #include <media/Metadata.h>  #include <media/AudioTrack.h> +#include <media/MemoryLeakTrackUtil.h>  #include <private/android_filesystem_config.h> @@ -392,139 +393,6 @@ static int myTid() {  #endif  } -#if defined(__arm__) -extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, -        size_t* infoSize, size_t* totalMemory, size_t* backtraceSize); -extern "C" void free_malloc_leak_info(uint8_t* info); - -// Use the String-class below instead of String8 to allocate all memory -// 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) { -        strcat(mPtr, s); -    } - -    const char *string() const { -        return mPtr; -    } - -    size_t size() const { -        return strlen(mPtr); -    } - -private: -    char *mPtr; - -    MyString8(const MyString8 &); -    MyString8 &operator=(const MyString8 &); -}; - -void memStatus(int fd, const Vector<String16>& args) -{ -    const size_t SIZE = 256; -    char buffer[SIZE]; -    MyString8 result; - -    typedef struct { -        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); -    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); -            ptr += sizeof(size_t); - -            e->dups = *reinterpret_cast<size_t *>(ptr); -            ptr += sizeof(size_t); - -            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); - -        for (size_t i = 0; i < count; i++) { -            AllocEntry *e = &entries[i]; - -            snprintf(buffer, SIZE, "size %8i, dup %4i, ", e->size, e->dups); -            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"); -        } - -        delete[] entries; -        free_malloc_leak_info(info); -    } - -    write(fd, result.string(), result.size()); -} -#endif -  status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)  {      const size_t SIZE = 256; @@ -623,7 +491,6 @@ status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)              result.append("\n");          } -#if defined(__arm__)          bool dumpMem = false;          for (size_t i = 0; i < args.size(); i++) {              if (args[i] == String16("-m")) { @@ -631,9 +498,8 @@ status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)              }          }          if (dumpMem) { -            memStatus(fd, args); +            dumpMemoryAddresses(fd);          } -#endif      }      write(fd, result.string(), result.size());      return NO_ERROR;  | 
