bool SkImageRef_ashmem::onDecode(SkImageDecoder* codec, SkStreamRewindable* stream, SkBitmap* bitmap, SkBitmap::Config config, SkImageDecoder::Mode mode) { if (SkImageDecoder::kDecodeBounds_Mode == mode) { return this->INHERITED::onDecode(codec, stream, bitmap, config, mode); } // Ashmem memory is guaranteed to be initialized to 0. codec->setSkipWritingZeroes(true); AshmemAllocator alloc(&fRec, this->getURI()); codec->setAllocator(&alloc); bool success = this->INHERITED::onDecode(codec, stream, bitmap, config, mode); // remove the allocator, since its on the stack codec->setAllocator(NULL); if (success) { // remember the colortable (if any) SkRefCnt_SafeAssign(fCT, bitmap->getColorTable()); return true; } else { if (fRec.fPinned) { ashmem_unpin_region(fRec.fFD, 0, 0); fRec.fPinned = false; } this->closeFD(); return false; } }
static void android_util_MemoryIntArray_close(JNIEnv* env, jobject clazz, jint fd, jlong ashmemAddr, jboolean owner) { if (fd < 0) { jniThrowException(env, "java/io/IOException", "bad file descriptor"); return; } int ashmemSize = ashmem_get_size_region(fd); if (ashmemSize <= 0) { jniThrowException(env, "java/io/IOException", "bad ashmem size"); return; } int unmapResult = munmap(reinterpret_cast<void *>(ashmemAddr), ashmemSize); if (unmapResult < 0) { jniThrowException(env, "java/io/IOException", "munmap failed"); return; } // We don't deallocate the atomic ints we created with placement new in the ashmem // region as the kernel we reclaim all pages when the ashmem region is destroyed. if (owner && (ashmem_unpin_region(fd, 0, 0) != ASHMEM_IS_UNPINNED)) { jniThrowException(env, "java/io/IOException", "ashmem unpinning failed"); return; } close(fd); }
bool SkImageRef_ashmem::onNewLockPixels(LockRec* rec) { SkASSERT(fBitmap.getPixels() == NULL); SkASSERT(fBitmap.getColorTable() == NULL); // fast case: check if we can just pin and get the cached data if (-1 != fRec.fFD) { SkASSERT(fRec.fAddr); SkASSERT(!fRec.fPinned); int pin = ashmem_pin_region(fRec.fFD, 0, 0); if (ASHMEM_NOT_PURGED == pin) { // yea, fast case! fBitmap.setPixels(fRec.fAddr, fCT); fRec.fPinned = true; } else if (ASHMEM_WAS_PURGED == pin) { ashmem_unpin_region(fRec.fFD, 0, 0); // let go of our colortable if we lost the pixels. Well get it back // again when we re-decode if (fCT) { fCT->unref(); fCT = NULL; } #if defined(DUMP_ASHMEM_LIFECYCLE) || defined(TRACE_ASH_PURGE) SkDebugf("===== ashmem purged %d\n", fBitmap.getSize()); #endif } else { SkDebugf("===== ashmem pin_region(%d) returned %d\n", fRec.fFD, pin); return false; } } else { // no FD, will create an ashmem region in allocator } return this->INHERITED::onNewLockPixels(rec); }
static void android_os_MemoryFile_pin(JNIEnv* env, jobject clazz, jobject fileDescriptor, jboolean pin) { int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); int result = (pin ? ashmem_pin_region(fd, 0, 0) : ashmem_unpin_region(fd, 0, 0)); if (result < 0) { jniThrowException(env, "java/io/IOException", NULL); } }
static jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz, jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset, jint count, jboolean unpinned) { int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) { ashmem_unpin_region(fd, 0, 0); jniThrowException(env, "java/io/IOException", "ashmem region was purged"); return -1; } env->GetByteArrayRegion(buffer, srcOffset, count, (jbyte *)address + destOffset); if (unpinned) { ashmem_unpin_region(fd, 0, 0); } return count; }
void SkImageRef_ashmem::onUnlockPixels() { this->INHERITED::onUnlockPixels(); if (-1 != fRec.fFD) { SkASSERT(fRec.fAddr); SkASSERT(fRec.fPinned); ashmem_unpin_region(fRec.fFD, 0, 0); fRec.fPinned = false; } // we clear this with or without an error, since we've either closed or // unpinned the region fBitmap.setPixels(NULL, NULL); }
status_t InputPublisher::reset() { #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' publisher ~ reset", mChannel->getName().string()); #endif if (mPinned) { // Destroy the semaphore since we are about to unpin the memory region that contains it. int result; if (mSemaphoreInitialized) { if (mSharedMessage->consumed) { result = sem_post(& mSharedMessage->semaphore); if (result < 0) { ALOGE("channel '%s' publisher ~ Error %d in sem_post.", mChannel->getName().string(), errno); return UNKNOWN_ERROR; } } result = sem_destroy(& mSharedMessage->semaphore); if (result < 0) { ALOGE("channel '%s' publisher ~ Error %d in sem_destroy.", mChannel->getName().string(), errno); return UNKNOWN_ERROR; } mSemaphoreInitialized = false; } // Unpin the region since we no longer care about its contents. int ashmemFd = mChannel->getAshmemFd(); result = ashmem_unpin_region(ashmemFd, 0, 0); if (result < 0) { ALOGE("channel '%s' publisher ~ Error %d unpinning ashmem fd %d.", mChannel->getName().string(), result, ashmemFd); return UNKNOWN_ERROR; } mPinned = false; } mMotionEventSampleDataTail = NULL; mWasDispatched = false; return OK; }
int test_ashmem(void) { int fd, ret; unsigned int *mAddress; unsigned char *buf = "ashmem test"; unsigned char read_buf[30]; unsigned int size = 0; fd = ashmem_open(NAME, LENGTH); if (fd < 0) printf("open ashmem error\n"); size = ioctl(fd, ASHMEM_GET_SIZE, NULL); printf("size=%d\n", size); mAddress = (unsigned int *)mmap(NULL, LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (mAddress < 0) printf("mmap failed\n"); ret = ashmem_write_bytes(fd, mAddress, buf, 0, 0, strlen(buf) + 1); if (ret < 0) printf("write failed\n"); ashmem_read_bytes(fd, mAddress, read_buf, 0, 0, strlen(buf) + 1); if (ret < 0) printf("read failed"); printf("read data: %s\n", read_buf); ashmem_unpin_region(fd, 0, 0); ret = munmap((void *)mAddress, LENGTH); if (ret < 0) printf("unmap failed\n"); close(fd); return ret; }
int shfile_server(void) { int fd, ret; unsigned int *mAddress; unsigned char *buf = "ashmem test"; unsigned char read_buf[30]; unsigned int size = 0; fd = ashmem_open(NAME, LENGTH); if (fd < 0) printf("open ashmem error\n"); size = ioctl(fd, ASHMEM_GET_SIZE, NULL); printf("size=%d\n", size); mAddress = (unsigned int *)mmap(NULL, LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (mAddress < 0) printf("mmap failed\n"); ret = ashmem_write_bytes(fd, mAddress, buf, 0, 0, strlen(buf) + 1); if (ret < 0) printf("write failed\n"); ashmem_read_bytes(fd, mAddress, read_buf, 0, 0, strlen(buf) + 1); if (ret < 0) printf("read failed"); printf("read data: %s\n", read_buf); ashmem_set_fd(fd); int key; initscr(); cbreak(); keypad(stdscr, TRUE); noecho(); timeout(1); clear(); mvprintw(5,5, "server running:"); while (1) { int i; move(7,0); clrtoeol(); refresh(); for (i = 0; i < 80; i++) { mvprintw(7, i, "."); refresh(); usleep(50000); key = getch(); if (key == 'q') break; } if (i < 80) break; } endwin(); ashmem_unpin_region(fd, 0, 0); ret = munmap((void *)mAddress, LENGTH); if (ret < 0) printf("unmap failed\n"); close(fd); return ret; }