IMemory.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /*
  2. * Copyright (C) 2008 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #define LOG_TAG "IMemory"
  17. #include <stdint.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <fcntl.h>
  21. #include <unistd.h>
  22. #include <sys/types.h>
  23. #include <sys/mman.h>
  24. #include <binder/IMemory.h>
  25. #include <cutils/log.h>
  26. #include <utils/KeyedVector.h>
  27. #include <utils/threads.h>
  28. #include <utils/Atomic.h>
  29. #include <binder/Parcel.h>
  30. #include <utils/CallStack.h>
  31. #ifdef USE_MEMORY_HEAP_ION
  32. #include "ion.h"
  33. #endif
  34. #define VERBOSE 0
  35. namespace android {
  36. // ---------------------------------------------------------------------------
  37. class HeapCache : public IBinder::DeathRecipient
  38. {
  39. public:
  40. HeapCache();
  41. virtual ~HeapCache();
  42. virtual void binderDied(const wp<IBinder>& who);
  43. sp<IMemoryHeap> find_heap(const sp<IBinder>& binder);
  44. void free_heap(const sp<IBinder>& binder);
  45. sp<IMemoryHeap> get_heap(const sp<IBinder>& binder);
  46. void dump_heaps();
  47. private:
  48. // For IMemory.cpp
  49. struct heap_info_t {
  50. sp<IMemoryHeap> heap;
  51. int32_t count;
  52. };
  53. void free_heap(const wp<IBinder>& binder);
  54. Mutex mHeapCacheLock;
  55. KeyedVector< wp<IBinder>, heap_info_t > mHeapCache;
  56. };
  57. static sp<HeapCache> gHeapCache = new HeapCache();
  58. /******************************************************************************/
  59. enum {
  60. HEAP_ID = IBinder::FIRST_CALL_TRANSACTION
  61. };
  62. class BpMemoryHeap : public BpInterface<IMemoryHeap>
  63. {
  64. public:
  65. BpMemoryHeap(const sp<IBinder>& impl);
  66. virtual ~BpMemoryHeap();
  67. virtual int getHeapID() const;
  68. virtual void* getBase() const;
  69. virtual size_t getSize() const;
  70. virtual uint32_t getFlags() const;
  71. virtual uint32_t getOffset() const;
  72. private:
  73. friend class IMemory;
  74. friend class HeapCache;
  75. // for debugging in this module
  76. static inline sp<IMemoryHeap> find_heap(const sp<IBinder>& binder) {
  77. return gHeapCache->find_heap(binder);
  78. }
  79. static inline void free_heap(const sp<IBinder>& binder) {
  80. gHeapCache->free_heap(binder);
  81. }
  82. static inline sp<IMemoryHeap> get_heap(const sp<IBinder>& binder) {
  83. return gHeapCache->get_heap(binder);
  84. }
  85. static inline void dump_heaps() {
  86. gHeapCache->dump_heaps();
  87. }
  88. void assertMapped() const;
  89. void assertReallyMapped() const;
  90. mutable volatile int32_t mHeapId;
  91. mutable void* mBase;
  92. mutable size_t mSize;
  93. mutable uint32_t mFlags;
  94. mutable uint32_t mOffset;
  95. mutable bool mRealHeap;
  96. mutable Mutex mLock;
  97. };
  98. // ----------------------------------------------------------------------------
  99. enum {
  100. GET_MEMORY = IBinder::FIRST_CALL_TRANSACTION
  101. };
  102. class BpMemory : public BpInterface<IMemory>
  103. {
  104. public:
  105. BpMemory(const sp<IBinder>& impl);
  106. virtual ~BpMemory();
  107. virtual sp<IMemoryHeap> getMemory(ssize_t* offset=0, size_t* size=0) const;
  108. private:
  109. mutable sp<IMemoryHeap> mHeap;
  110. mutable ssize_t mOffset;
  111. mutable size_t mSize;
  112. };
  113. /******************************************************************************/
  114. void* IMemory::fastPointer(const sp<IBinder>& binder, ssize_t offset) const
  115. {
  116. sp<IMemoryHeap> realHeap = BpMemoryHeap::get_heap(binder);
  117. void* const base = realHeap->base();
  118. if (base == MAP_FAILED)
  119. return 0;
  120. return static_cast<char*>(base) + offset;
  121. }
  122. void* IMemory::pointer() const {
  123. ssize_t offset;
  124. sp<IMemoryHeap> heap = getMemory(&offset);
  125. void* const base = heap!=0 ? heap->base() : MAP_FAILED;
  126. if (base == MAP_FAILED)
  127. return 0;
  128. return static_cast<char*>(base) + offset;
  129. }
  130. size_t IMemory::size() const {
  131. size_t size;
  132. getMemory(NULL, &size);
  133. return size;
  134. }
  135. ssize_t IMemory::offset() const {
  136. ssize_t offset;
  137. getMemory(&offset);
  138. return offset;
  139. }
  140. /******************************************************************************/
  141. BpMemory::BpMemory(const sp<IBinder>& impl)
  142. : BpInterface<IMemory>(impl), mOffset(0), mSize(0)
  143. {
  144. }
  145. BpMemory::~BpMemory()
  146. {
  147. }
  148. sp<IMemoryHeap> BpMemory::getMemory(ssize_t* offset, size_t* size) const
  149. {
  150. if (mHeap == 0) {
  151. Parcel data, reply;
  152. data.writeInterfaceToken(IMemory::getInterfaceDescriptor());
  153. if (remote()->transact(GET_MEMORY, data, &reply) == NO_ERROR) {
  154. sp<IBinder> heap = reply.readStrongBinder();
  155. ssize_t o = reply.readInt32();
  156. size_t s = reply.readInt32();
  157. if (heap != 0) {
  158. mHeap = interface_cast<IMemoryHeap>(heap);
  159. if (mHeap != 0) {
  160. size_t heapSize = mHeap->getSize();
  161. if (s <= heapSize
  162. && o >= 0
  163. && (static_cast<size_t>(o) <= heapSize - s)) {
  164. mOffset = o;
  165. mSize = s;
  166. } else {
  167. // Hm.
  168. android_errorWriteWithInfoLog(0x534e4554,
  169. "26877992", -1, NULL, 0);
  170. mOffset = 0;
  171. mSize = 0;
  172. }
  173. }
  174. }
  175. }
  176. }
  177. if (offset) *offset = mOffset;
  178. if (size) *size = mSize;
  179. return (mSize > 0) ? mHeap : 0;
  180. }
  181. // ---------------------------------------------------------------------------
  182. IMPLEMENT_META_INTERFACE(Memory, "android.utils.IMemory");
  183. BnMemory::BnMemory() {
  184. }
  185. BnMemory::~BnMemory() {
  186. }
  187. status_t BnMemory::onTransact(
  188. uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
  189. {
  190. switch(code) {
  191. case GET_MEMORY: {
  192. CHECK_INTERFACE(IMemory, data, reply);
  193. ssize_t offset;
  194. size_t size;
  195. reply->writeStrongBinder( IInterface::asBinder(getMemory(&offset, &size)) );
  196. reply->writeInt32(offset);
  197. reply->writeInt32(size);
  198. return NO_ERROR;
  199. } break;
  200. default:
  201. return BBinder::onTransact(code, data, reply, flags);
  202. }
  203. }
  204. /******************************************************************************/
  205. BpMemoryHeap::BpMemoryHeap(const sp<IBinder>& impl)
  206. : BpInterface<IMemoryHeap>(impl),
  207. mHeapId(-1), mBase(MAP_FAILED), mSize(0), mFlags(0), mOffset(0), mRealHeap(false)
  208. {
  209. }
  210. BpMemoryHeap::~BpMemoryHeap() {
  211. if (mHeapId != -1) {
  212. close(mHeapId);
  213. if (mRealHeap) {
  214. // by construction we're the last one
  215. if (mBase != MAP_FAILED) {
  216. sp<IBinder> binder = IInterface::asBinder(this);
  217. if (VERBOSE) {
  218. ALOGD("UNMAPPING binder=%p, heap=%p, size=%zu, fd=%d",
  219. binder.get(), this, mSize, mHeapId);
  220. CallStack stack(LOG_TAG);
  221. }
  222. munmap(mBase, mSize);
  223. }
  224. } else {
  225. // remove from list only if it was mapped before
  226. sp<IBinder> binder = IInterface::asBinder(this);
  227. free_heap(binder);
  228. }
  229. }
  230. }
  231. void BpMemoryHeap::assertMapped() const
  232. {
  233. if (mHeapId == -1) {
  234. sp<IBinder> binder(IInterface::asBinder(const_cast<BpMemoryHeap*>(this)));
  235. sp<BpMemoryHeap> heap(static_cast<BpMemoryHeap*>(find_heap(binder).get()));
  236. heap->assertReallyMapped();
  237. if (heap->mBase != MAP_FAILED) {
  238. Mutex::Autolock _l(mLock);
  239. if (mHeapId == -1) {
  240. mBase = heap->mBase;
  241. mSize = heap->mSize;
  242. mOffset = heap->mOffset;
  243. android_atomic_write( dup( heap->mHeapId ), &mHeapId );
  244. }
  245. } else {
  246. // something went wrong
  247. free_heap(binder);
  248. }
  249. }
  250. }
  251. void BpMemoryHeap::assertReallyMapped() const
  252. {
  253. if (mHeapId == -1) {
  254. // remote call without mLock held, worse case scenario, we end up
  255. // calling transact() from multiple threads, but that's not a problem,
  256. // only mmap below must be in the critical section.
  257. Parcel data, reply;
  258. data.writeInterfaceToken(IMemoryHeap::getInterfaceDescriptor());
  259. status_t err = remote()->transact(HEAP_ID, data, &reply);
  260. int parcel_fd = reply.readFileDescriptor();
  261. ssize_t size = reply.readInt32();
  262. uint32_t flags = reply.readInt32();
  263. uint32_t offset = reply.readInt32();
  264. ALOGE_IF(err, "binder=%p transaction failed fd=%d, size=%zd, err=%d (%s)",
  265. IInterface::asBinder(this).get(),
  266. parcel_fd, size, err, strerror(-err));
  267. #ifdef USE_MEMORY_HEAP_ION
  268. ion_client ion_client_num = -1;
  269. if (flags & USE_ION_FD) {
  270. ion_client_num = ion_client_create();
  271. ALOGE_IF(ion_client_num < 0, "BpMemoryHeap : ion client creation error");
  272. }
  273. #endif
  274. int fd = dup( parcel_fd );
  275. ALOGE_IF(fd==-1, "cannot dup fd=%d, size=%zd, err=%d (%s)",
  276. parcel_fd, size, err, strerror(errno));
  277. int access = PROT_READ;
  278. if (!(flags & READ_ONLY)) {
  279. access |= PROT_WRITE;
  280. }
  281. Mutex::Autolock _l(mLock);
  282. if (mHeapId == -1) {
  283. mRealHeap = true;
  284. #ifdef USE_MEMORY_HEAP_ION
  285. if (flags & USE_ION_FD) {
  286. if (ion_client_num < 0)
  287. mBase = MAP_FAILED;
  288. else
  289. mBase = ion_map(fd, size, offset);
  290. } else
  291. #endif
  292. mBase = mmap(0, size, access, MAP_SHARED, fd, offset);
  293. if (mBase == MAP_FAILED) {
  294. ALOGE("cannot map BpMemoryHeap (binder=%p), size=%zd, fd=%d (%s)",
  295. IInterface::asBinder(this).get(), size, fd, strerror(errno));
  296. close(fd);
  297. } else {
  298. mSize = size;
  299. mFlags = flags;
  300. mOffset = offset;
  301. android_atomic_write(fd, &mHeapId);
  302. }
  303. }
  304. #ifdef USE_MEMORY_HEAP_ION
  305. if (ion_client_num < 0)
  306. ion_client_num = -1;
  307. else
  308. ion_client_destroy(ion_client_num);
  309. #endif
  310. }
  311. }
  312. int BpMemoryHeap::getHeapID() const {
  313. assertMapped();
  314. return mHeapId;
  315. }
  316. void* BpMemoryHeap::getBase() const {
  317. assertMapped();
  318. return mBase;
  319. }
  320. size_t BpMemoryHeap::getSize() const {
  321. assertMapped();
  322. return mSize;
  323. }
  324. uint32_t BpMemoryHeap::getFlags() const {
  325. assertMapped();
  326. return mFlags;
  327. }
  328. uint32_t BpMemoryHeap::getOffset() const {
  329. assertMapped();
  330. return mOffset;
  331. }
  332. // ---------------------------------------------------------------------------
  333. IMPLEMENT_META_INTERFACE(MemoryHeap, "android.utils.IMemoryHeap");
  334. BnMemoryHeap::BnMemoryHeap() {
  335. }
  336. BnMemoryHeap::~BnMemoryHeap() {
  337. }
  338. status_t BnMemoryHeap::onTransact(
  339. uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
  340. {
  341. switch(code) {
  342. case HEAP_ID: {
  343. CHECK_INTERFACE(IMemoryHeap, data, reply);
  344. reply->writeFileDescriptor(getHeapID());
  345. reply->writeInt32(getSize());
  346. reply->writeInt32(getFlags());
  347. reply->writeInt32(getOffset());
  348. return NO_ERROR;
  349. } break;
  350. default:
  351. return BBinder::onTransact(code, data, reply, flags);
  352. }
  353. }
  354. /*****************************************************************************/
  355. HeapCache::HeapCache()
  356. : DeathRecipient()
  357. {
  358. }
  359. HeapCache::~HeapCache()
  360. {
  361. }
  362. void HeapCache::binderDied(const wp<IBinder>& binder)
  363. {
  364. //ALOGD("binderDied binder=%p", binder.unsafe_get());
  365. free_heap(binder);
  366. }
  367. sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder)
  368. {
  369. Mutex::Autolock _l(mHeapCacheLock);
  370. ssize_t i = mHeapCache.indexOfKey(binder);
  371. if (i>=0) {
  372. heap_info_t& info = mHeapCache.editValueAt(i);
  373. ALOGD_IF(VERBOSE,
  374. "found binder=%p, heap=%p, size=%zu, fd=%d, count=%d",
  375. binder.get(), info.heap.get(),
  376. static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
  377. static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
  378. info.count);
  379. android_atomic_inc(&info.count);
  380. return info.heap;
  381. } else {
  382. heap_info_t info;
  383. info.heap = interface_cast<IMemoryHeap>(binder);
  384. info.count = 1;
  385. //ALOGD("adding binder=%p, heap=%p, count=%d",
  386. // binder.get(), info.heap.get(), info.count);
  387. mHeapCache.add(binder, info);
  388. return info.heap;
  389. }
  390. }
  391. void HeapCache::free_heap(const sp<IBinder>& binder) {
  392. free_heap( wp<IBinder>(binder) );
  393. }
  394. void HeapCache::free_heap(const wp<IBinder>& binder)
  395. {
  396. sp<IMemoryHeap> rel;
  397. {
  398. Mutex::Autolock _l(mHeapCacheLock);
  399. ssize_t i = mHeapCache.indexOfKey(binder);
  400. if (i>=0) {
  401. heap_info_t& info(mHeapCache.editValueAt(i));
  402. int32_t c = android_atomic_dec(&info.count);
  403. if (c == 1) {
  404. ALOGD_IF(VERBOSE,
  405. "removing binder=%p, heap=%p, size=%zu, fd=%d, count=%d",
  406. binder.unsafe_get(), info.heap.get(),
  407. static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
  408. static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
  409. info.count);
  410. rel = mHeapCache.valueAt(i).heap;
  411. mHeapCache.removeItemsAt(i);
  412. }
  413. } else {
  414. ALOGE("free_heap binder=%p not found!!!", binder.unsafe_get());
  415. }
  416. }
  417. }
  418. sp<IMemoryHeap> HeapCache::get_heap(const sp<IBinder>& binder)
  419. {
  420. sp<IMemoryHeap> realHeap;
  421. Mutex::Autolock _l(mHeapCacheLock);
  422. ssize_t i = mHeapCache.indexOfKey(binder);
  423. if (i>=0) realHeap = mHeapCache.valueAt(i).heap;
  424. else realHeap = interface_cast<IMemoryHeap>(binder);
  425. return realHeap;
  426. }
  427. void HeapCache::dump_heaps()
  428. {
  429. Mutex::Autolock _l(mHeapCacheLock);
  430. int c = mHeapCache.size();
  431. for (int i=0 ; i<c ; i++) {
  432. const heap_info_t& info = mHeapCache.valueAt(i);
  433. BpMemoryHeap const* h(static_cast<BpMemoryHeap const *>(info.heap.get()));
  434. ALOGD("hey=%p, heap=%p, count=%d, (fd=%d, base=%p, size=%zu)",
  435. mHeapCache.keyAt(i).unsafe_get(),
  436. info.heap.get(), info.count,
  437. h->mHeapId, h->mBase, h->mSize);
  438. }
  439. }
  440. // ---------------------------------------------------------------------------
  441. }; // namespace android