Пример #1
0
TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) {
    sp<InputChannel> serverChannel, clientChannel;

    status_t result = InputChannel::openInputChannelPair(String8("channel name"),
            serverChannel, clientChannel);

    ASSERT_EQ(OK, result)
            << "should have successfully opened a channel pair";

    // Name
    EXPECT_STREQ("channel name (server)", serverChannel->getName().string())
            << "server channel should have suffixed name";
    EXPECT_STREQ("channel name (client)", clientChannel->getName().string())
            << "client channel should have suffixed name";

    // Ashmem uniqueness
    EXPECT_NE(serverChannel->getAshmemFd(), clientChannel->getAshmemFd())
            << "server and client channel should have different ashmem fds because it was dup'd";

    // Ashmem usability
    ssize_t serverAshmemSize = ashmem_get_size_region(serverChannel->getAshmemFd());
    ssize_t clientAshmemSize = ashmem_get_size_region(clientChannel->getAshmemFd());
    uint32_t* serverAshmem = static_cast<uint32_t*>(mmap(NULL, serverAshmemSize,
            PROT_READ | PROT_WRITE, MAP_SHARED, serverChannel->getAshmemFd(), 0));
    uint32_t* clientAshmem = static_cast<uint32_t*>(mmap(NULL, clientAshmemSize,
            PROT_READ | PROT_WRITE, MAP_SHARED, clientChannel->getAshmemFd(), 0));
    ASSERT_TRUE(serverAshmem != NULL)
            << "server channel ashmem should be mappable";
    ASSERT_TRUE(clientAshmem != NULL)
            << "client channel ashmem should be mappable";
    *serverAshmem = 0xf00dd00d;
    EXPECT_EQ(0xf00dd00d, *clientAshmem)
            << "ashmem buffer should be shared by client and server";
    munmap(serverAshmem, serverAshmemSize);
    munmap(clientAshmem, clientAshmemSize);

    // Server->Client communication
    EXPECT_EQ(OK, serverChannel->sendSignal('S'))
            << "server channel should be able to send signal to client channel";
    char signal;
    EXPECT_EQ(OK, clientChannel->receiveSignal(& signal))
            << "client channel should be able to receive signal from server channel";
    EXPECT_EQ('S', signal)
            << "client channel should receive the correct signal from server channel";

    // Client->Server communication
    EXPECT_EQ(OK, clientChannel->sendSignal('c'))
            << "client channel should be able to send signal to server channel";
    EXPECT_EQ(OK, serverChannel->receiveSignal(& signal))
            << "server channel should be able to receive signal from client channel";
    EXPECT_EQ('c', signal)
            << "server channel should receive the correct signal from client channel";
}
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);
}
void ProfileDataContainer::switchStorageToAshmem(int ashmemfd) {
    int regionSize = ashmem_get_size_region(ashmemfd);
    if (regionSize < 0) {
        int err = errno;
        ALOGW("Failed to get ashmem region size from fd %d, err %d %s", ashmemfd, err,
              strerror(err));
        return;
    }
    if (regionSize < static_cast<int>(sizeof(ProfileData))) {
        ALOGW("Ashmem region is too small! Received %d, required %u", regionSize,
              static_cast<unsigned int>(sizeof(ProfileData)));
        return;
    }
    ProfileData* newData = reinterpret_cast<ProfileData*>(
            mmap(NULL, sizeof(ProfileData), PROT_READ | PROT_WRITE, MAP_SHARED, ashmemfd, 0));
    if (newData == MAP_FAILED) {
        int err = errno;
        ALOGW("Failed to move profile data to ashmem fd %d, error = %d", ashmemfd, err);
        return;
    }

    newData->mergeWith(*mData);
    freeData();
    mData = newData;
    mIsMapped = true;
}
status_t InputConsumer::initialize() {
#if DEBUG_TRANSPORT_ACTIONS
    ALOGD("channel '%s' consumer ~ initialize",
            mChannel->getName().string());
#endif

    int ashmemFd = mChannel->getAshmemFd();
    int result = ashmem_get_size_region(ashmemFd);
    if (result < 0) {
        ALOGE("channel '%s' consumer ~ Error %d getting size of ashmem fd %d.",
                mChannel->getName().string(), result, ashmemFd);
        return UNKNOWN_ERROR;
    }

    mAshmemSize = (size_t) result;

    mSharedMessage = static_cast<InputMessage*>(mmap(NULL, mAshmemSize,
            PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0));
    if (! mSharedMessage) {
        ALOGE("channel '%s' consumer ~ mmap failed on ashmem fd %d.",
                mChannel->getName().string(), ashmemFd);
        return NO_MEMORY;
    }

    return OK;
}
status_t CursorWindow::createFromParcel(Parcel* parcel, CursorWindow** outCursorWindow) {
    String8 name = parcel->readString8();

    status_t result;
    int ashmemFd = parcel->readFileDescriptor();
    if (ashmemFd == int(BAD_TYPE)) {
        result = BAD_TYPE;
    } else {
        ssize_t size = ashmem_get_size_region(ashmemFd);
        if (size < 0) {
            result = UNKNOWN_ERROR;
        } else {
            int dupAshmemFd = ::fcntl(ashmemFd, F_DUPFD_CLOEXEC, 0);
            if (dupAshmemFd < 0) {
                result = -errno;
            } else {
                // the size of the ashmem descriptor can be modified between ashmem_get_size_region
                // call and mmap, so we'll check again immediately after memory is mapped
                void* data = ::mmap(NULL, size, PROT_READ, MAP_SHARED, dupAshmemFd, 0);
                if (data == MAP_FAILED) {
                    result = -errno;
                } else if (ashmem_get_size_region(dupAshmemFd) != size) {
                    ::munmap(data, size);
                    result = BAD_VALUE;
                } else {
                    CursorWindow* window = new CursorWindow(name, dupAshmemFd,
                            data, size, true /*readOnly*/);
                    LOG_WINDOW("Created CursorWindow from parcel: 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;
                }
                ::close(dupAshmemFd);
            }
        }
    }
    *outCursorWindow = NULL;
    return result;
}
static jint android_util_MemoryIntArray_size(JNIEnv* env, jobject clazz, jint fd) {
    if (fd < 0) {
        jniThrowException(env, "java/io/IOException", "bad file descriptor");
        return -1;
    }

    int ashmemSize = ashmem_get_size_region(fd);
    if (ashmemSize < 0) {
        // Some other error, throw exception
        jniThrowIOException(env, errno);
        return -1;
    }
    return ashmemSize / sizeof(std::atomic_int);
}
static jboolean android_os_MemoryFile_is_ashmem_region(JNIEnv* env, jobject clazz,
        jobject fileDescriptor) {
    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
    // Use ASHMEM_GET_SIZE to find out if the fd refers to an ashmem region.
    // ASHMEM_GET_SIZE should succeed for all ashmem regions, and the kernel
    // should return ENOTTY for all other valid file descriptors
    int result = ashmem_get_size_region(fd);
    if (result < 0) {
        if (errno == ENOTTY) {
            // ENOTTY means that the ioctl does not apply to this object,
            // i.e., it is not an ashmem region.
            return JNI_FALSE;
        }
        // Some other error, throw exception
        jniThrowIOException(env, errno);
        return JNI_FALSE;
    }
    return JNI_TRUE;
}
Пример #8
0
android::status_t NativeCursorWindow::createFromParcel(IParcel* parcel, NativeCursorWindow** outCursorWindow)
{
    android::Parcel* p;
    parcel->GetDataPayload((Handle32*)&p);

    android::String8 str8(p->readString8());
    String name(str8.string());

    android::status_t result;
    int ashmemFd = p->readFileDescriptor();
    if (ashmemFd == int(android::BAD_TYPE)) {
        result = android::BAD_TYPE;
    } else {
        ssize_t size = ashmem_get_size_region(ashmemFd);
        if (size < 0) {
            result = android::UNKNOWN_ERROR;
        } else {
            int dupAshmemFd = ::dup(ashmemFd);
            if (dupAshmemFd < 0) {
                result = -errno;
            } else {
                void* data = ::mmap(NULL, size, PROT_READ, MAP_SHARED, dupAshmemFd, 0);
                if (data == MAP_FAILED) {
                    result = -errno;
                } else {
                    NativeCursorWindow* window = new NativeCursorWindow(name, dupAshmemFd,
                            data, size, true /*readOnly*/);
                    LOG_WINDOW("Created NativeCursorWindow from parcel: 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 android::OK;
                }
                ::close(dupAshmemFd);
            }
        }
    }
    *outCursorWindow = NULL;
    return result;
}
Пример #9
0
status_t CursorWindow::createFromParcel(Parcel* parcel, CursorWindow** outCursorWindow) {
    String8 name = parcel->readString8();

    status_t result;
    int ashmemFd = parcel->readFileDescriptor();
    if (ashmemFd == int(BAD_TYPE)) {
        result = BAD_TYPE;
        ALOG(LOG_ERROR,LOG_TAG,"CursorWindow::createFromParcel, BAD_TYPE:%d",result);
    } else {
        ssize_t size = ashmem_get_size_region(ashmemFd);
        if (size < 0) {
            result = UNKNOWN_ERROR;
            ALOG(LOG_ERROR,LOG_TAG,"CursorWindow::createFromParcel, UNKNOWN_ERROR:%d",result);
        } else {
            int dupAshmemFd = ::dup(ashmemFd);
            if (dupAshmemFd < 0) {
                result = -errno;
                ALOG(LOG_ERROR,LOG_TAG,"CursorWindow::createFromParcel, dup return errno = %d",errno);   
            } else {
                void* data = ::mmap(NULL, size, PROT_READ, MAP_SHARED, dupAshmemFd, 0);
                if (data == MAP_FAILED) {
                    result = -errno;
                    ALOG(LOG_ERROR,LOG_TAG,"CursorWindow::createFromParcel, mmap return errno = %d",errno);
                } else {
                    CursorWindow* window = new CursorWindow(name, dupAshmemFd,
                            data, size, true /*readOnly*/);
                    LOG_WINDOW("Created CursorWindow from parcel: 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;
                }
                ::close(dupAshmemFd);
            }
        }
    }
    *outCursorWindow = NULL;
    return result;
}
static jlong android_util_MemoryIntArray_open(JNIEnv* env, jobject clazz, jint fd,
    jboolean owner, jboolean writable)
{
    if (fd < 0) {
        jniThrowException(env, "java/io/IOException", "bad file descriptor");
        return -1;
    }

    int ashmemSize = ashmem_get_size_region(fd);
    if (ashmemSize <= 0) {
        jniThrowException(env, "java/io/IOException", "bad ashmem size");
        return -1;
    }

    int protMode = (owner || writable) ? (PROT_READ | PROT_WRITE) : PROT_READ;
    void* ashmemAddr = mmap(NULL, ashmemSize, protMode, MAP_SHARED, fd, 0);
    if (ashmemAddr == MAP_FAILED) {
        jniThrowException(env, "java/io/IOException", "cannot mmap ashmem");
        return -1;
    }

    if (owner) {
        int size = ashmemSize / sizeof(std::atomic_int);
        new (ashmemAddr) std::atomic_int[size];
    }

    if (owner && !writable) {
        int setProtResult = ashmem_set_prot_region(fd, PROT_READ);
        if (setProtResult < 0) {
            jniThrowException(env, "java/io/IOException", "cannot set ashmem prot mode");
            return -1;
        }
    }

    return reinterpret_cast<jlong>(ashmemAddr);
}