From 41066ed56592a4348220f9b292cf623bcb79f3c9 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Sun, 8 Aug 2010 00:29:51 -0400 Subject: [PATCH] HACK: Allow use of Eclair MemoryDealer for compatibility. Take #2. --- core/jni/Android.mk | 4 +- core/jni/CursorWindow.cpp | 19 +- core/jni/CursorWindow.h | 12 +- include/binder/MemoryDealer.h | 5 + include/binder/MemoryDealerEclair.h | 257 +++++++++++ include/binder/MemoryHeapPmem.h | 10 +- libs/audioflinger/AudioFlinger.cpp | 4 + libs/audioflinger/AudioFlinger.h | 4 + libs/binder/Android.mk | 8 +- libs/binder/MemoryDealerEclair.cpp | 422 ++++++++++++++++++ libs/binder/MemoryHeapPmem.cpp | 4 + media/libmedia/Android.mk | 4 +- media/libmedia/AudioRecord.cpp | 4 + media/libmedia/AudioTrack.cpp | 4 + .../MetadataRetrieverClient.cpp | 42 ++ .../MetadataRetrieverClient.h | 5 +- media/libstagefright/OMXCodec.cpp | 5 +- media/libstagefright/omx/tests/OMXHarness.cpp | 8 + 18 files changed, 810 insertions(+), 11 deletions(-) create mode 100644 include/binder/MemoryDealerEclair.h create mode 100644 libs/binder/MemoryDealerEclair.cpp diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 6edc45f9604be..bd0f30710be85 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -185,8 +185,8 @@ LOCAL_SHARED_LIBRARIES := \ ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true) LOCAL_SHARED_LIBRARIES += \ - libsurfaceflinger_client \ - libcamera_client + libsurfaceflinger_client \ + libcamera_client endif ifeq ($(BOARD_HAVE_BLUETOOTH),true) diff --git a/core/jni/CursorWindow.cpp b/core/jni/CursorWindow.cpp index 78779214b6ed1..f0895839b40cf 100644 --- a/core/jni/CursorWindow.cpp +++ b/core/jni/CursorWindow.cpp @@ -18,9 +18,12 @@ #define LOG_TAG "CursorWindow" #include +#ifdef USE_ECLAIR_MEMORYDEALER +#include +#else #include #include - +#endif #include #include #include @@ -38,7 +41,11 @@ CursorWindow::CursorWindow(size_t maxSize) : { } +#ifdef USE_ECLAIR_MEMORYDEALER +bool CursorWindow::setMemory(sp memory) +#else bool CursorWindow::setMemory(const sp& memory) +#endif { mMemory = memory; mData = (uint8_t *) memory->pointer(); @@ -48,6 +55,9 @@ bool CursorWindow::setMemory(const sp& memory) mHeader = (window_header_t *) mData; // Make the window read-only +#ifdef USE_ECLAIR_MEMORYDEALER + mHeap = NULL; +#endif ssize_t size = memory->size(); mSize = size; mMaxSize = size; @@ -59,11 +69,16 @@ LOG_WINDOW("Created CursorWindow from existing IMemory: mFreeOffset = %d, numRow bool CursorWindow::initBuffer(bool localOnly) { //TODO Use a non-memory dealer mmap region for localOnly - +#ifdef USE_ECLAIR_MEMORYDEALER + mHeap = new MemoryDealer(new SharedHeap(mMaxSize, 0, "CursorWindow")); + if (mHeap != NULL) { + mMemory = mHeap->allocate(mMaxSize); +#else sp heap; heap = new MemoryHeapBase(mMaxSize, 0, "CursorWindow"); if (heap != NULL) { mMemory = new MemoryBase(heap, 0, mMaxSize); +#endif if (mMemory != NULL) { mData = (uint8_t *) mMemory->pointer(); if (mData) { diff --git a/core/jni/CursorWindow.h b/core/jni/CursorWindow.h index 3fcb560227207..f5d791a36a543 100644 --- a/core/jni/CursorWindow.h +++ b/core/jni/CursorWindow.h @@ -21,9 +21,12 @@ #include #include +#ifdef USE_ECLAIR_MEMORYDEALER +#include +#else #include #include - +#endif #include #define DEFAULT_WINDOW_SIZE 4096 @@ -101,7 +104,11 @@ class CursorWindow public: CursorWindow(size_t maxSize); CursorWindow(){} +#ifdef USE_ECLAIR_MEMORYDEALER + bool setMemory(sp); +#else bool setMemory(const sp&); +#endif ~CursorWindow(); bool initBuffer(bool localOnly); @@ -189,6 +196,9 @@ class CursorWindow size_t mSize; size_t mMaxSize; window_header_t * mHeader; +#ifdef USE_ECLAIR_MEMORYDEALER + sp mHeap; +#endif sp mMemory; /** diff --git a/include/binder/MemoryDealer.h b/include/binder/MemoryDealer.h index 170f20d67a023..2512c2731c23e 100644 --- a/include/binder/MemoryDealer.h +++ b/include/binder/MemoryDealer.h @@ -14,6 +14,10 @@ * limitations under the License. */ +#ifdef USE_ECLAIR_MEMORYDEALER +#include +#else + #ifndef ANDROID_MEMORY_DEALER_H #define ANDROID_MEMORY_DEALER_H @@ -58,3 +62,4 @@ class MemoryDealer : public RefBase }; // namespace android #endif // ANDROID_MEMORY_DEALER_H +#endif // USE_ECLAIR_MEMORYDEALER diff --git a/include/binder/MemoryDealerEclair.h b/include/binder/MemoryDealerEclair.h new file mode 100644 index 0000000000000..03ac70a6b325f --- /dev/null +++ b/include/binder/MemoryDealerEclair.h @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2007 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 ANDROID_MEMORY_DEALER_H +#define ANDROID_MEMORY_DEALER_H + + +#include +#include + +#include +#include +#include + +namespace android { +// ---------------------------------------------------------------------------- +class String8; + +/* + * interface for implementing a "heap". A heap basically provides + * the IMemoryHeap interface for cross-process sharing and the + * ability to map/unmap pages within the heap. + */ +class HeapInterface : public virtual BnMemoryHeap +{ +public: + // all values must be page-aligned + virtual sp mapMemory(size_t offset, size_t size) = 0; + + HeapInterface(); +protected: + virtual ~HeapInterface(); +}; + +// ---------------------------------------------------------------------------- + +/* + * interface for implementing an allocator. An allocator provides + * methods for allocating and freeing memory blocks and dumping + * its state. + */ +class AllocatorInterface : public RefBase +{ +public: + enum { + PAGE_ALIGNED = 0x00000001 + }; + + virtual size_t allocate(size_t size, uint32_t flags = 0) = 0; + virtual status_t deallocate(size_t offset) = 0; + virtual size_t size() const = 0; + virtual void dump(const char* what, uint32_t flags = 0) const = 0; + virtual void dump(String8& res, + const char* what, uint32_t flags = 0) const = 0; + + AllocatorInterface(); +protected: + virtual ~AllocatorInterface(); +}; + +// ---------------------------------------------------------------------------- + +/* + * concrete implementation of HeapInterface on top of mmap() + */ +class SharedHeap : public HeapInterface, public MemoryHeapBase +{ +public: + SharedHeap(); + SharedHeap(size_t size, uint32_t flags = 0, char const * name = NULL); + virtual ~SharedHeap(); + virtual sp mapMemory(size_t offset, size_t size); +}; + +// ---------------------------------------------------------------------------- + +/* + * A simple templatized doubly linked-list implementation + */ + +template +class LinkedList +{ + NODE* mFirst; + NODE* mLast; + +public: + LinkedList() : mFirst(0), mLast(0) { } + bool isEmpty() const { return mFirst == 0; } + NODE const* head() const { return mFirst; } + NODE* head() { return mFirst; } + NODE const* tail() const { return mLast; } + NODE* tail() { return mLast; } + + void insertAfter(NODE* node, NODE* newNode) { + newNode->prev = node; + newNode->next = node->next; + if (node->next == 0) mLast = newNode; + else node->next->prev = newNode; + node->next = newNode; + } + + void insertBefore(NODE* node, NODE* newNode) { + newNode->prev = node->prev; + newNode->next = node; + if (node->prev == 0) mFirst = newNode; + else node->prev->next = newNode; + node->prev = newNode; + } + + void insertHead(NODE* newNode) { + if (mFirst == 0) { + mFirst = mLast = newNode; + newNode->prev = newNode->next = 0; + } else { + newNode->prev = 0; + newNode->next = mFirst; + mFirst->prev = newNode; + mFirst = newNode; + } + } + + void insertTail(NODE* newNode) { + if (mLast == 0) { + insertHead(newNode); + } else { + newNode->prev = mLast; + newNode->next = 0; + mLast->next = newNode; + mLast = newNode; + } + } + + NODE* remove(NODE* node) { + if (node->prev == 0) mFirst = node->next; + else node->prev->next = node->next; + if (node->next == 0) mLast = node->prev; + else node->next->prev = node->prev; + return node; + } +}; + + +/* + * concrete implementation of AllocatorInterface using a simple + * best-fit allocation scheme + */ +class SimpleBestFitAllocator : public AllocatorInterface +{ +public: + + SimpleBestFitAllocator(size_t size); + virtual ~SimpleBestFitAllocator(); + + virtual size_t allocate(size_t size, uint32_t flags = 0); + virtual status_t deallocate(size_t offset); + virtual size_t size() const; + virtual void dump(const char* what, uint32_t flags = 0) const; + virtual void dump(String8& res, + const char* what, uint32_t flags = 0) const; + +private: + + struct chunk_t { + chunk_t(size_t start, size_t size) + : start(start), size(size), free(1), prev(0), next(0) { + } + size_t start; + size_t size : 28; + int free : 4; + mutable chunk_t* prev; + mutable chunk_t* next; + }; + + ssize_t alloc(size_t size, uint32_t flags); + chunk_t* dealloc(size_t start); + void dump_l(const char* what, uint32_t flags = 0) const; + void dump_l(String8& res, const char* what, uint32_t flags = 0) const; + + static const int kMemoryAlign; + mutable Mutex mLock; + LinkedList mList; + size_t mHeapSize; +}; + +// ---------------------------------------------------------------------------- + +class MemoryDealer : public RefBase +{ +public: + + enum { + READ_ONLY = MemoryHeapBase::READ_ONLY, + PAGE_ALIGNED = AllocatorInterface::PAGE_ALIGNED + }; + + // creates a memory dealer with the SharedHeap and SimpleBestFitAllocator + MemoryDealer(size_t size, uint32_t flags = 0, const char* name = 0); + + // provide a custom heap but use the SimpleBestFitAllocator + MemoryDealer(const sp& heap); + + // provide both custom heap and allocotar + MemoryDealer( + const sp& heap, + const sp& allocator); + + virtual sp allocate(size_t size, uint32_t flags = 0); + virtual void deallocate(size_t offset); + virtual void dump(const char* what, uint32_t flags = 0) const; + + + sp getMemoryHeap() const { return heap(); } + sp getAllocator() const { return allocator(); } + +protected: + virtual ~MemoryDealer(); + +private: + const sp& heap() const; + const sp& allocator() const; + + class Allocation : public BnMemory { + public: + Allocation(const sp& dealer, + ssize_t offset, size_t size, const sp& memory); + virtual ~Allocation(); + virtual sp getMemory(ssize_t* offset, size_t* size) const; + private: + sp mDealer; + ssize_t mOffset; + size_t mSize; + sp mMemory; + }; + + sp mHeap; + sp mAllocator; +}; + + +// ---------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_MEMORY_DEALER_H diff --git a/include/binder/MemoryHeapPmem.h b/include/binder/MemoryHeapPmem.h index e1660c4bb13a5..02e83f8b18eaa 100644 --- a/include/binder/MemoryHeapPmem.h +++ b/include/binder/MemoryHeapPmem.h @@ -20,18 +20,26 @@ #include #include +#ifdef USE_ECLAIR_MEMORYDEALER +#include +#endif #include #include #include +#ifndef USE_ECLAIR_MEMORYDEALER #include +#endif namespace android { class MemoryHeapBase; // --------------------------------------------------------------------------- - +#ifdef USE_ECLAIR_MEMORYDEALER +class MemoryHeapPmem : public HeapInterface, public MemoryHeapBase +#else class MemoryHeapPmem : public MemoryHeapBase +#endif { public: class MemoryPmem : public BnMemory { diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index a2fbca1a902a2..890692df929a1 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -3069,7 +3069,11 @@ void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue() AudioFlinger::Client::Client(const sp& audioFlinger, pid_t pid) : RefBase(), mAudioFlinger(audioFlinger), +#ifdef USE_ECLAIR_MEMORYDEALER + mMemoryDealer(new MemoryDealer(1024*1024)), +#else mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")), +#endif mPid(pid) { // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h index 8f99cf89c5159..05915e5aa2b2d 100644 --- a/libs/audioflinger/AudioFlinger.h +++ b/libs/audioflinger/AudioFlinger.h @@ -31,7 +31,11 @@ #include #include #include +#ifdef USE_ECLAIR_MEMORYDEALER #include +#else +#include +#endif #include #include diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk index 13dc500d9445a..85cd488ef1786 100644 --- a/libs/binder/Android.mk +++ b/libs/binder/Android.mk @@ -21,7 +21,6 @@ sources := \ IPCThreadState.cpp \ IPermissionController.cpp \ IServiceManager.cpp \ - MemoryDealer.cpp \ MemoryBase.cpp \ MemoryHeapBase.cpp \ MemoryHeapPmem.cpp \ @@ -30,6 +29,13 @@ sources := \ ProcessState.cpp \ Static.cpp +ifeq ($(BOARD_USES_ECLAIR_LIBCAMERA),true) + LOCAL_CFLAGS += -DUSE_ECLAIR_MEMORYDEALER + sources += MemoryDealerEclair.cpp +else + sources += MemoryDealer.cpp +endif + LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) diff --git a/libs/binder/MemoryDealerEclair.cpp b/libs/binder/MemoryDealerEclair.cpp new file mode 100644 index 0000000000000..a48a619e09233 --- /dev/null +++ b/libs/binder/MemoryDealerEclair.cpp @@ -0,0 +1,422 @@ +/* + * Copyright (C) 2007 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. + */ + +#define LOG_TAG "MemoryDealer" +#define USE_ECLAIR_MEMORYDEALER + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace android { +// ---------------------------------------------------------------------------- + +HeapInterface::HeapInterface() { } +HeapInterface::~HeapInterface() { } + +// ---------------------------------------------------------------------------- + +AllocatorInterface::AllocatorInterface() { } +AllocatorInterface::~AllocatorInterface() { } + +// ---------------------------------------------------------------------------- + +class SimpleMemory : public MemoryBase { +public: + SimpleMemory(const sp& heap, ssize_t offset, size_t size); + virtual ~SimpleMemory(); +}; + + +// ---------------------------------------------------------------------------- + +MemoryDealer::Allocation::Allocation( + const sp& dealer, ssize_t offset, size_t size, + const sp& memory) + : mDealer(dealer), mOffset(offset), mSize(size), mMemory(memory) +{ +} + +MemoryDealer::Allocation::~Allocation() +{ + if (mSize) { + /* NOTE: it's VERY important to not free allocations of size 0 because + * they're special as they don't have any record in the allocator + * and could alias some real allocation (their offset is zero). */ + mDealer->deallocate(mOffset); + } +} + +sp MemoryDealer::Allocation::getMemory( + ssize_t* offset, size_t* size) const +{ + return mMemory->getMemory(offset, size); +} + +// ---------------------------------------------------------------------------- + +MemoryDealer::MemoryDealer(size_t size, uint32_t flags, const char* name) + : mHeap(new SharedHeap(size, flags, name)), + mAllocator(new SimpleBestFitAllocator(size)) +{ +} + +MemoryDealer::MemoryDealer(const sp& heap) + : mHeap(heap), + mAllocator(new SimpleBestFitAllocator(heap->virtualSize())) +{ +} + +MemoryDealer::MemoryDealer( const sp& heap, + const sp& allocator) + : mHeap(heap), mAllocator(allocator) +{ +} + +MemoryDealer::~MemoryDealer() +{ +} + +sp MemoryDealer::allocate(size_t size, uint32_t flags) +{ + sp memory; + const ssize_t offset = allocator()->allocate(size, flags); + if (offset >= 0) { + sp new_memory = heap()->mapMemory(offset, size); + if (new_memory != 0) { + memory = new Allocation(this, offset, size, new_memory); + } else { + LOGE("couldn't map [%8lx, %u]", offset, size); + if (size) { + /* NOTE: it's VERY important to not free allocations of size 0 + * because they're special as they don't have any record in the + * allocator and could alias some real allocation + * (their offset is zero). */ + allocator()->deallocate(offset); + } + } + } + return memory; +} + +void MemoryDealer::deallocate(size_t offset) +{ + allocator()->deallocate(offset); +} + +void MemoryDealer::dump(const char* what, uint32_t flags) const +{ + allocator()->dump(what, flags); +} + +const sp& MemoryDealer::heap() const { + return mHeap; +} + +const sp& MemoryDealer::allocator() const { + return mAllocator; +} + +// ---------------------------------------------------------------------------- + +// align all the memory blocks on a cache-line boundary +const int SimpleBestFitAllocator::kMemoryAlign = 32; + +SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size) +{ + size_t pagesize = getpagesize(); + mHeapSize = ((size + pagesize-1) & ~(pagesize-1)); + + chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign); + mList.insertHead(node); +} + +SimpleBestFitAllocator::~SimpleBestFitAllocator() +{ + while(!mList.isEmpty()) { + delete mList.remove(mList.head()); + } +} + +size_t SimpleBestFitAllocator::size() const +{ + return mHeapSize; +} + +size_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) +{ + Mutex::Autolock _l(mLock); + ssize_t offset = alloc(size, flags); + return offset; +} + +status_t SimpleBestFitAllocator::deallocate(size_t offset) +{ + Mutex::Autolock _l(mLock); + chunk_t const * const freed = dealloc(offset); + if (freed) { + return NO_ERROR; + } + return NAME_NOT_FOUND; +} + +ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags) +{ + if (size == 0) { + return 0; + } + size = (size + kMemoryAlign-1) / kMemoryAlign; + chunk_t* free_chunk = 0; + chunk_t* cur = mList.head(); + + size_t pagesize = getpagesize(); + while (cur) { + int extra = 0; + if (flags & PAGE_ALIGNED) + extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ; + + // best fit + if (cur->free && (cur->size >= (size+extra))) { + if ((!free_chunk) || (cur->size < free_chunk->size)) { + free_chunk = cur; + } + if (cur->size == size) { + break; + } + } + cur = cur->next; + } + + if (free_chunk) { + const size_t free_size = free_chunk->size; + free_chunk->free = 0; + free_chunk->size = size; + if (free_size > size) { + int extra = 0; + if (flags & PAGE_ALIGNED) + extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ; + if (extra) { + chunk_t* split = new chunk_t(free_chunk->start, extra); + free_chunk->start += extra; + mList.insertBefore(free_chunk, split); + } + + LOGE_IF((flags&PAGE_ALIGNED) && + ((free_chunk->start*kMemoryAlign)&(pagesize-1)), + "PAGE_ALIGNED requested, but page is not aligned!!!"); + + const ssize_t tail_free = free_size - (size+extra); + if (tail_free > 0) { + chunk_t* split = new chunk_t( + free_chunk->start + free_chunk->size, tail_free); + mList.insertAfter(free_chunk, split); + } + } + return (free_chunk->start)*kMemoryAlign; + } + return NO_MEMORY; +} + +SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start) +{ + start = start / kMemoryAlign; + chunk_t* cur = mList.head(); + while (cur) { + if (cur->start == start) { + LOG_FATAL_IF(cur->free, + "block at offset 0x%08lX of size 0x%08lX already freed", + cur->start*kMemoryAlign, cur->size*kMemoryAlign); + + // merge freed blocks together + chunk_t* freed = cur; + cur->free = 1; + do { + chunk_t* const p = cur->prev; + chunk_t* const n = cur->next; + if (p && (p->free || !cur->size)) { + freed = p; + p->size += cur->size; + mList.remove(cur); + delete cur; + } + cur = n; + } while (cur && cur->free); + + #ifndef NDEBUG + if (!freed->free) { + dump_l("dealloc (!freed->free)"); + } + #endif + LOG_FATAL_IF(!freed->free, + "freed block at offset 0x%08lX of size 0x%08lX is not free!", + freed->start * kMemoryAlign, freed->size * kMemoryAlign); + + return freed; + } + cur = cur->next; + } + return 0; +} + +void SimpleBestFitAllocator::dump(const char* what, uint32_t flags) const +{ + Mutex::Autolock _l(mLock); + dump_l(what, flags); +} + +void SimpleBestFitAllocator::dump_l(const char* what, uint32_t flags) const +{ + String8 result; + dump_l(result, what, flags); + LOGD("%s", result.string()); +} + +void SimpleBestFitAllocator::dump(String8& result, + const char* what, uint32_t flags) const +{ + Mutex::Autolock _l(mLock); + dump_l(result, what, flags); +} + +void SimpleBestFitAllocator::dump_l(String8& result, + const char* what, uint32_t flags) const +{ + size_t size = 0; + int32_t i = 0; + chunk_t const* cur = mList.head(); + + const size_t SIZE = 256; + char buffer[SIZE]; + snprintf(buffer, SIZE, " %s (%p, size=%u)\n", + what, this, (unsigned int)mHeapSize); + + result.append(buffer); + + while (cur) { + const char* errs[] = {"", "| link bogus NP", + "| link bogus PN", "| link bogus NP+PN" }; + int np = ((cur->next) && cur->next->prev != cur) ? 1 : 0; + int pn = ((cur->prev) && cur->prev->next != cur) ? 2 : 0; + + snprintf(buffer, SIZE, " %3u: %08x | 0x%08X | 0x%08X | %s %s\n", + i, int(cur), int(cur->start*kMemoryAlign), + int(cur->size*kMemoryAlign), + int(cur->free) ? "F" : "A", + errs[np|pn]); + + result.append(buffer); + + if (!cur->free) + size += cur->size*kMemoryAlign; + + i++; + cur = cur->next; + } + snprintf(buffer, SIZE, " size allocated: %u (%u KB)\n", int(size), int(size/1024)); + result.append(buffer); +} + +// ---------------------------------------------------------------------------- + +SharedHeap::SharedHeap() + : HeapInterface(), MemoryHeapBase() +{ +} + +SharedHeap::SharedHeap(size_t size, uint32_t flags, char const * name) + : MemoryHeapBase(size, flags, name) +{ +} + +SharedHeap::~SharedHeap() +{ +} + +sp SharedHeap::mapMemory(size_t offset, size_t size) +{ + return new SimpleMemory(this, offset, size); +} + + +SimpleMemory::SimpleMemory(const sp& heap, + ssize_t offset, size_t size) + : MemoryBase(heap, offset, size) +{ +#ifndef NDEBUG + void* const start_ptr = (void*)(intptr_t(heap->base()) + offset); + memset(start_ptr, 0xda, size); +#endif +} + +SimpleMemory::~SimpleMemory() +{ + size_t freedOffset = getOffset(); + size_t freedSize = getSize(); + + // keep the size to unmap in excess + size_t pagesize = getpagesize(); + size_t start = freedOffset; + size_t end = start + freedSize; + start &= ~(pagesize-1); + end = (end + pagesize-1) & ~(pagesize-1); + + // give back to the kernel the pages we don't need + size_t free_start = freedOffset; + size_t free_end = free_start + freedSize; + if (start < free_start) + start = free_start; + if (end > free_end) + end = free_end; + start = (start + pagesize-1) & ~(pagesize-1); + end &= ~(pagesize-1); + + if (start < end) { + void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + start); + size_t size = end-start; + +#ifndef NDEBUG + memset(start_ptr, 0xdf, size); +#endif + + // MADV_REMOVE is not defined on Dapper based Goobuntu +#ifdef MADV_REMOVE + if (size) { + int err = madvise(start_ptr, size, MADV_REMOVE); + LOGW_IF(err, "madvise(%p, %u, MADV_REMOVE) returned %s", + start_ptr, size, err<0 ? strerror(errno) : "Ok"); + } +#endif + } +} + +}; // namespace android diff --git a/libs/binder/MemoryHeapPmem.cpp b/libs/binder/MemoryHeapPmem.cpp index 16e92f939ee3e..5cc60f8994171 100644 --- a/libs/binder/MemoryHeapPmem.cpp +++ b/libs/binder/MemoryHeapPmem.cpp @@ -127,7 +127,11 @@ void SubRegionMemory::revoke() MemoryHeapPmem::MemoryHeapPmem(const sp& pmemHeap, uint32_t flags) +#ifdef USE_ECLAIR_MEMORYDEALER + : HeapInterface(), MemoryHeapBase() +#else : MemoryHeapBase() +#endif { char const * const device = pmemHeap->getDevice(); #if HAVE_ANDROID_OS diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index b660eecd81493..02b8324902114 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -33,8 +33,8 @@ LOCAL_SHARED_LIBRARIES := \ ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true) LOCAL_SHARED_LIBRARIES += \ - libsurfaceflinger_client \ - libcamera_client + libsurfaceflinger_client \ + libcamera_client endif LOCAL_MODULE:= libmedia diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index ad037d6e42b40..4e387733ad68f 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -37,6 +37,10 @@ #include #include +#ifdef USE_ECLAIR_MEMORYDEALER +#include +#endif + #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index cd7bcd5be3bb9..ba99d815ae2f0 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -37,6 +37,10 @@ #include #include +#ifdef USE_ECLAIR_MEMORYDEALER +#include +#endif + #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp index 550b84dfb3470..070680ec86797 100644 --- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp +++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp @@ -28,8 +28,12 @@ #include #include #include +#ifdef USE_ECLAIR_MEMORYDEALER +#include +#else #include #include +#endif #include #include #include @@ -63,6 +67,10 @@ MetadataRetrieverClient::MetadataRetrieverClient(pid_t pid) { LOGV("MetadataRetrieverClient constructor pid(%d)", pid); mPid = pid; +#ifdef USE_ECLAIR_MEMORYDEALER + mThumbnailDealer = NULL; + mAlbumArtDealer = NULL; +#endif mThumbnail = NULL; mAlbumArt = NULL; mRetriever = NULL; @@ -93,6 +101,10 @@ void MetadataRetrieverClient::disconnect() LOGV("disconnect from pid %d", mPid); Mutex::Autolock lock(mLock); mRetriever.clear(); +#ifdef USE_ECLAIR_MEMORYDEALER + mThumbnailDealer.clear(); + mAlbumArtDealer.clear(); +#endif mThumbnail.clear(); mAlbumArt.clear(); mMode = METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL; @@ -239,6 +251,9 @@ sp MetadataRetrieverClient::captureFrame() LOGV("captureFrame"); Mutex::Autolock lock(mLock); mThumbnail.clear(); +#ifdef USE_ECLAIR_MEMORYDEALER + mThumbnailDealer.clear(); +#endif if (mRetriever == NULL) { LOGE("retriever is not initialized"); return NULL; @@ -249,15 +264,27 @@ sp MetadataRetrieverClient::captureFrame() return NULL; } size_t size = sizeof(VideoFrame) + frame->mSize; +#ifdef USE_ECLAIR_MEMORYDEALER + mThumbnailDealer = new MemoryDealer(size); + if (mThumbnailDealer == NULL) { +#else sp heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient"); if (heap == NULL) { +#endif LOGE("failed to create MemoryDealer"); delete frame; return NULL; } +#ifdef USE_ECLAIR_MEMORYDEALER + mThumbnail = mThumbnailDealer->allocate(size); +#else mThumbnail = new MemoryBase(heap, 0, size); +#endif if (mThumbnail == NULL) { LOGE("not enough memory for VideoFrame size=%u", size); +#ifdef USE_ECLAIR_MEMORYDEALER + mThumbnailDealer.clear(); +#endif delete frame; return NULL; } @@ -278,6 +305,9 @@ sp MetadataRetrieverClient::extractAlbumArt() LOGV("extractAlbumArt"); Mutex::Autolock lock(mLock); mAlbumArt.clear(); +#ifdef USE_ECLAIR_MEMORYDEALER + mAlbumArtDealer.clear(); +#endif if (mRetriever == NULL) { LOGE("retriever is not initialized"); return NULL; @@ -288,15 +318,27 @@ sp MetadataRetrieverClient::extractAlbumArt() return NULL; } size_t size = sizeof(MediaAlbumArt) + albumArt->mSize; +#ifdef USE_ECLAIR_MEMORYDEALER + mAlbumArtDealer = new MemoryDealer(size); + if (mAlbumArtDealer == NULL) { +#else sp heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient"); if (heap == NULL) { +#endif LOGE("failed to create MemoryDealer object"); delete albumArt; return NULL; } +#ifdef USE_ECLAIR_MEMORYDEALER + mAlbumArt = mAlbumArtDealer->allocate(size); +#else mAlbumArt = new MemoryBase(heap, 0, size); +#endif if (mAlbumArt == NULL) { LOGE("not enough memory for MediaAlbumArt size=%u", size); +#ifdef USE_ECLAIR_MEMORYDEALER + mAlbumArtDealer.clear(); +#endif delete albumArt; return NULL; } diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h index 4aab94fa7573b..7e6d2236b23de 100644 --- a/media/libmediaplayerservice/MetadataRetrieverClient.h +++ b/media/libmediaplayerservice/MetadataRetrieverClient.h @@ -24,7 +24,6 @@ #include #include #include - #include @@ -63,6 +62,10 @@ class MetadataRetrieverClient : public BnMediaMetadataRetriever int mMode; // Keep the shared memory copy of album art and capture frame (for thumbnail) +#ifdef USE_ECLAIR_MEMORYDEALER + sp mAlbumArtDealer; + sp mThumbnailDealer; +#endif sp mAlbumArt; sp mThumbnail; }; diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 69da7efe69153..e9a724889a703 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -1211,8 +1211,11 @@ status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) { } size_t totalSize = def.nBufferCountActual * def.nBufferSize; +#ifdef USE_ECLAIR_MEMORYDEALER + mDealer[portIndex] = new MemoryDealer(totalSize); +#else mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec"); - +#endif for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { sp mem = mDealer[portIndex]->allocate(def.nBufferSize); CHECK(mem.get() != NULL); diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp index fcf506dcde2fd..0245c11570f06 100644 --- a/media/libstagefright/omx/tests/OMXHarness.cpp +++ b/media/libstagefright/omx/tests/OMXHarness.cpp @@ -24,7 +24,11 @@ #include #include +#ifdef USE_ECLAIR_MEMORYDEALER #include +#else +#include +#endif #include #include #include @@ -286,7 +290,11 @@ status_t Harness::testStateTransitions( return OK; } +#ifdef USE_ECLAIR_MEMORYDEALER + sp dealer = new MemoryDealer(8 * 1024 * 1024); +#else sp dealer = new MemoryDealer(8 * 1024 * 1024, "OMXHarness"); +#endif IOMX::node_id node; status_t err =