diff options
-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; |