status_t CursorWindow::create(const String8& name, size_t size, CursorWindow** outCursorWindow) { String8 ashmemName("CursorWindow: "); ashmemName.append(name); status_t result; int ashmemFd = ashmem_create_region(ashmemName.string(), size); if (ashmemFd < 0) { ALOG(LOG_ERROR,LOG_TAG,"CursorWindow::create, ashmem_create_region return errno = %d",errno); result = -errno; } else { result = ashmem_set_prot_region(ashmemFd, PROT_READ | PROT_WRITE); if (result >= 0) { void* data = ::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0); if (data == MAP_FAILED) { ALOG(LOG_ERROR,LOG_TAG,"CursorWindow::create, mmap return errno = %d",errno); result = -errno; } else { result = ashmem_set_prot_region(ashmemFd, PROT_READ); if (result >= 0) { CursorWindow* window = new CursorWindow(name, ashmemFd, data, size, false /*readOnly*/); result = window->clear(); if (!result) { LOG_WINDOW("Created new CursorWindow: freeOffset=%d, " "numRows=%d, numColumns=%d, mSize=%d, mData=%p", window->mHeader->freeOffset, window->mHeader->numRows, window->mHeader->numColumns, window->mSize, window->mData); *outCursorWindow = window; return OK; } ALOG(LOG_ERROR,LOG_TAG,"CursorWindow::create, window->clear return errno = %d",errno); delete window; } else { ALOG(LOG_ERROR,LOG_TAG,"CursorWindow::create, ashmeme_set_prot_region return errno = %d",errno); } } ::munmap(data, size); } ::close(ashmemFd); } *outCursorWindow = NULL; return result; }
status_t InputChannel::openInputChannelPair(const String8& name, sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) { status_t result; String8 ashmemName("InputChannel "); ashmemName.append(name); int serverAshmemFd = ashmem_create_region(ashmemName.string(), DEFAULT_MESSAGE_BUFFER_SIZE); if (serverAshmemFd < 0) { result = -errno; ALOGE("channel '%s' ~ Could not create shared memory region. errno=%d", name.string(), errno); } else { result = ashmem_set_prot_region(serverAshmemFd, PROT_READ | PROT_WRITE); if (result < 0) { ALOGE("channel '%s' ~ Error %d trying to set protection of ashmem fd %d.", name.string(), result, serverAshmemFd); } else { // Dup the file descriptor because the server and client input channel objects that // are returned may have different lifetimes but they share the same shared memory region. int clientAshmemFd; clientAshmemFd = dup(serverAshmemFd); if (clientAshmemFd < 0) { result = -errno; ALOGE("channel '%s' ~ Could not dup() shared memory region fd. errno=%d", name.string(), errno); } else { int forward[2]; if (pipe(forward)) { result = -errno; ALOGE("channel '%s' ~ Could not create forward pipe. errno=%d", name.string(), errno); } else { int reverse[2]; if (pipe(reverse)) { result = -errno; ALOGE("channel '%s' ~ Could not create reverse pipe. errno=%d", name.string(), errno); } else { String8 serverChannelName = name; serverChannelName.append(" (server)"); outServerChannel = new InputChannel(serverChannelName, serverAshmemFd, reverse[0], forward[1]); String8 clientChannelName = name; clientChannelName.append(" (client)"); outClientChannel = new InputChannel(clientChannelName, clientAshmemFd, forward[0], reverse[1]); return OK; } ::close(forward[0]); ::close(forward[1]); } ::close(clientAshmemFd); } } ::close(serverAshmemFd); } outServerChannel.clear(); outClientChannel.clear(); return result; }