static jdouble nativeGetDouble(JNIEnv* env, jclass clazz, jint windowPtr, jint row, jint column) { CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); LOG_WINDOW("Getting double for %d,%d from %p", row, column, window); CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); if (!fieldSlot) { throwExceptionWithRowCol(env, row, column); return 0.0; } int32_t type = window->getFieldSlotType(fieldSlot); if (type == CursorWindow::FIELD_TYPE_FLOAT) { return window->getFieldSlotValueDouble(fieldSlot); } else if (type == CursorWindow::FIELD_TYPE_STRING) { size_t sizeIncludingNull; const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); return sizeIncludingNull > 1 ? strtod(value, NULL) : 0.0; } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { return jdouble(window->getFieldSlotValueLong(fieldSlot)); } else if (type == CursorWindow::FIELD_TYPE_NULL) { return 0.0; } else if (type == CursorWindow::FIELD_TYPE_BLOB) { throw_sqlite3_exception(env, "Unable to convert BLOB to double"); return 0.0; } else { throwUnknownTypeException(env, type); return 0.0; } }
static void nativeDispose(JNIEnv* env, jclass clazz, jint windowPtr) { CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); if (window) { LOG_WINDOW("Closing window %p", window); delete window; } }
static jbyteArray getBlob_native(JNIEnv* env, jobject object, jint row, jint column) { int32_t err; CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Getting blob for %d,%d from %p", row, column, window); field_slot_t field; err = window->read_field_slot(row, column, &field); if (err != 0) { throwExceptionWithRowCol(env, row, column); return NULL; } uint8_t type = field.type; if (type == FIELD_TYPE_BLOB || type == FIELD_TYPE_STRING) { jbyteArray byteArray = env->NewByteArray(field.data.buffer.size); LOG_ASSERT(byteArray, "Native could not create new byte[]"); env->SetByteArrayRegion(byteArray, 0, field.data.buffer.size, (const jbyte*)window->offsetToPtr(field.data.buffer.offset)); return byteArray; } else if (type == FIELD_TYPE_INTEGER) { throw_sqlite3_exception(env, "INTEGER data in getBlob_native "); } else if (type == FIELD_TYPE_FLOAT) { throw_sqlite3_exception(env, "FLOAT data in getBlob_native "); } else if (type == FIELD_TYPE_NULL) { // do nothing } else { throwUnknowTypeException(env, type); } return NULL; }
static jbyteArray nativeGetBlob(JNIEnv* env, jclass clazz, jint windowPtr, jint row, jint column) { CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); LOG_WINDOW("Getting blob for %d,%d from %p", row, column, window); CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); if (!fieldSlot) { throwExceptionWithRowCol(env, row, column); return NULL; } int32_t type = window->getFieldSlotType(fieldSlot); if (type == CursorWindow::FIELD_TYPE_BLOB || type == CursorWindow::FIELD_TYPE_STRING) { size_t size; const void* value = window->getFieldSlotValueBlob(fieldSlot, &size); jbyteArray byteArray = env->NewByteArray(size); if (!byteArray) { env->ExceptionClear(); throw_sqlite3_exception(env, "Native could not create new byte[]"); return NULL; } env->SetByteArrayRegion(byteArray, 0, size, static_cast<const jbyte*>(value)); return byteArray; } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { throw_sqlite3_exception(env, "INTEGER data in nativeGetBlob "); } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { throw_sqlite3_exception(env, "FLOAT data in nativeGetBlob "); } else if (type == CursorWindow::FIELD_TYPE_NULL) { // do nothing } else { throwUnknownTypeException(env, type); } return NULL; }
android::status_t NativeCursorWindow::allocRow() { if (mReadOnly) { return android::INVALID_OPERATION; } // Fill in the row slot RowSlot* rowSlot = allocRowSlot(); if (rowSlot == NULL) { return android::NO_MEMORY; } // Allocate the slots for the field directory size_t fieldDirSize = mHeader->numColumns * sizeof(FieldSlot); uint32_t fieldDirOffset = alloc(fieldDirSize, true /*aligned*/); if (!fieldDirOffset) { mHeader->numRows--; LOG_WINDOW("The row failed, so back out the new row accounting " "from allocRowSlot %d", mHeader->numRows); return android::NO_MEMORY; } FieldSlot* fieldDir = static_cast<FieldSlot*>(offsetToPtr(fieldDirOffset)); memset(fieldDir, 0, fieldDirSize); // LOG_WINDOW("Allocated row %u, rowSlot is at offset %u, fieldDir is %d bytes at offset %u\n", // mHeader->numRows - 1, offsetFromPtr(rowSlot), fieldDirSize, fieldDirOffset); rowSlot->offset = fieldDirOffset; return android::OK; }
static jboolean nativePutBlob(JNIEnv* env, jclass clazz, jlong windowPtr, jbyteArray valueObj, jint row, jint column) { CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); jsize len = env->GetArrayLength(valueObj); void* value = env->GetPrimitiveArrayCritical(valueObj, NULL); status_t status = window->putBlob(row, column, value, len); env->ReleasePrimitiveArrayCritical(valueObj, value, JNI_ABORT); if (status) { LOG_WINDOW("Failed to put blob. error=%d", status); return false; } LOG_WINDOW("%d,%d is BLOB with %u bytes", row, column, len); return true; }
static jstring getString_native(JNIEnv* env, jobject object, jint row, jint column) { int32_t err; CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Getting string for %d,%d from %p", row, column, window); field_slot_t field; err = window->read_field_slot(row, column, &field); if (err != 0) { throwExceptionWithRowCol(env, row, column); return NULL; } uint8_t type = field.type; if (type == FIELD_TYPE_STRING) { uint32_t size = field.data.buffer.size; if (size > 0) { #if WINDOW_STORAGE_UTF8 // Pass size - 1 since the UTF8 is null terminated and we don't want a null terminator on the UTF16 string String16 utf16((char const *)window->offsetToPtr(field.data.buffer.offset), size - 1); return env->NewString((jchar const *)utf16.string(), utf16.size()); #else return env->NewString((jchar const *)window->offsetToPtr(field.data.buffer.offset), size / 2); #endif } else { return env->NewStringUTF(""); } } else if (type == FIELD_TYPE_INTEGER) { int64_t value; if (window->getLong(row, column, &value)) { char buf[32]; snprintf(buf, sizeof(buf), "%lld", value); return env->NewStringUTF(buf); } return NULL; } else if (type == FIELD_TYPE_FLOAT) { double value; if (window->getDouble(row, column, &value)) { char buf[32]; //selete the print way by code to impove the precision if (((value > 0.0001) && (value < 1000000)) || ((value < -0.0001) && (value > -1000000))) snprintf(buf, sizeof(buf), "%lf", value); else snprintf(buf, sizeof(buf), "%e", value); return env->NewStringUTF(buf); } return NULL; } else if (type == FIELD_TYPE_NULL) { return NULL; } else if (type == FIELD_TYPE_BLOB) { throw_sqlite3_exception(env, "Unable to convert BLOB to string"); return NULL; } else { throwUnknowTypeException(env, type); return NULL; } }
static void native_close(JNIEnv * env, jobject object) { CursorWindow * window = GET_WINDOW(env, object); if (window) { LOG_WINDOW("Closing window %p", window); delete window; SET_WINDOW(env, object, 0); } }
static void native_clear(JNIEnv * env, jobject object) { CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Clearing window %p", window); if (window == NULL) { jniThrowException(env, "java/lang/IllegalStateException", "clear() called after close()"); return; } window->clear(); }
static jint nativeGetType(JNIEnv* env, jclass clazz, jlong windowPtr, jint row, jint column) { CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); LOG_WINDOW("returning column type affinity for %d,%d from %p", row, column, window); CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); if (!fieldSlot) { return CursorWindow::FIELD_TYPE_NULL; } return window->getFieldSlotType(fieldSlot); }
static jboolean nativePutString(JNIEnv* env, jclass clazz, jlong windowPtr, jstring valueObj, jint row, jint column) { CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); size_t sizeIncludingNull = env->GetStringUTFLength(valueObj) + 1; const char* valueStr = env->GetStringUTFChars(valueObj, NULL); if (!valueStr) { LOG_WINDOW("value can't be transferred to UTFChars"); return false; } status_t status = window->putString(row, column, valueStr, sizeIncludingNull); env->ReleaseStringUTFChars(valueObj, valueStr); if (status) { LOG_WINDOW("Failed to put string. error=%d", status); return false; } LOG_WINDOW("%d,%d is TEXT with %u bytes", row, column, sizeIncludingNull); return true; }
bool CursorWindow::initBuffer(bool localOnly) { void* data = malloc(mMaxSize); if(data){ mData = (uint8_t *) data; mHeader = (window_header_t *) mData; mSize = mMaxSize; clear(); LOG_WINDOW("Created CursorWindow with new MemoryDealer: mFreeOffset = %d, mSize = %d, mMaxSize = %d, mData = %p", mFreeOffset, mSize, mMaxSize, mData); return true; } return false; }
static jboolean isNull_native(JNIEnv* env, jobject object, jint row, jint column) { CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Checking for NULL at %d,%d from %p", row, column, window); bool isNull; if (window->getNull(row, column, &isNull)) { return isNull; } //TODO throw execption? return true; }
static jint nativeCreateFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj) { Parcel* parcel = parcelForJavaObject(env, parcelObj); CursorWindow* window; status_t status = CursorWindow::createFromParcel(parcel, &window); if (status || !window) { LOGE("Could not create CursorWindow from Parcel due to error %d.", status); return 0; } LOG_WINDOW("nativeInitializeFromBinder: numRows = %d, numColumns = %d, window = %p", window->getNumRows(), window->getNumColumns(), window); return reinterpret_cast<jint>(window); }
static jint nativeGetType(JNIEnv* env, jclass clazz, jlong windowPtr, jint row, jint column) { CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); LOG_WINDOW("returning column type affinity for %d,%d from %p", row, column, window); CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); if (!fieldSlot) { // FIXME: This is really broken but we have CTS tests that depend // on this legacy behavior. //throwExceptionWithRowCol(env, row, column); return CursorWindow::FIELD_TYPE_NULL; } return window->getFieldSlotType(fieldSlot); }
static jdouble getDouble_native(JNIEnv* env, jobject object, jint row, jint column) { int32_t err; CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Getting double for %d,%d from %p", row, column, window); field_slot_t field; err = window->read_field_slot(row, column, &field); if (err != 0) { throwExceptionWithRowCol(env, row, column); return 0.0; } uint8_t type = field.type; if (type == FIELD_TYPE_FLOAT) { double value; if (window->getDouble(row, column, &value)) { return value; } return 0.0; } else if (type == FIELD_TYPE_STRING) { uint32_t size = field.data.buffer.size; if (size > 0) { #if WINDOW_STORAGE_UTF8 return strtod((char const *)window->offsetToPtr(field.data.buffer.offset), NULL); #else String8 ascii((char16_t *) window->offsetToPtr(field.data.buffer.offset), size / 2); char const * str = ascii.string(); return strtod(str, NULL); #endif } else { return 0.0; } } else if (type == FIELD_TYPE_INTEGER) { int64_t value; if (window->getLong(row, column, &value)) { return (double) value; } return 0.0; } else if (type == FIELD_TYPE_NULL) { return 0.0; } else if (type == FIELD_TYPE_BLOB) { throw_sqlite3_exception(env, "Unable to convert BLOB to double"); return 0.0; } else { throwUnknowTypeException(env, type); return 0.0; } }
static jdouble getDouble_native(JNIEnv* env, jobject object, jint row, jint column) { int32_t err; CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Getting double for %d,%d from %p", row, column, window); field_slot_t field; err = window->read_field_slot(row, column, &field); if (err != 0) { throwExceptionWithRowCol(env, row, column); return 0.0; } uint8_t type = field.type; if (type == FIELD_TYPE_FLOAT) { double value; if (window->getDouble(row, column, &value)) { return value; } return 0.0; } else if (type == FIELD_TYPE_STRING) { uint32_t size = field.data.buffer.size; if (size > 0) { double result; jstring data = env->NewString((const jchar*)window->offsetToPtr(field.data.buffer.offset), (jsize)size); const char* utf8data = env->GetStringUTFChars(data, NULL); result = strtod(utf8data, NULL); if(utf8data) env->ReleaseStringUTFChars(data, utf8data); if(data) env->DeleteLocalRef(data); return result; } else { return 0.0; } } else if (type == FIELD_TYPE_INTEGER) { int64_t value; if (window->getLong(row, column, &value)) { return (double) value; } return 0.0; } else if (type == FIELD_TYPE_NULL) { return 0.0; } else if (type == FIELD_TYPE_BLOB) { throw_sqlite3_exception(env, "Unable to convert BLOB to double"); return 0.0; } else { throwUnknowTypeException(env, type); return 0.0; } }
static jboolean isFloat_native(JNIEnv* env, jobject object, jint row, jint column) { int32_t err; CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Checking if column is a float for %d,%d from %p", row, column, window); field_slot_t field; err = window->read_field_slot(row, column, &field); if (err != 0) { throwExceptionWithRowCol(env, row, column); return NULL; } return field.type == FIELD_TYPE_FLOAT; }
static jint getType_native(JNIEnv* env, jobject object, jint row, jint column) { int32_t err; CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Getting type for %d,%d from %p", row, column, window); field_slot_t field; err = window->read_field_slot(row, column, &field); if (err != 0) { throwExceptionWithRowCol(env, row, column); return NULL; } return field.type; }
static jlong nativeCreate(JNIEnv* env, jclass clazz, jstring nameObj, jint cursorWindowSize) { const char* nameStr = env->GetStringUTFChars(nameObj, NULL); std::string name(nameStr); env->ReleaseStringUTFChars(nameObj, nameStr); CursorWindow* window; status_t status = CursorWindow::create(name, cursorWindowSize, &window); if (status || !window) { ALOGE("Could not allocate CursorWindow of size %d due to error %d.", cursorWindowSize, status); return 0; } LOG_WINDOW("nativeInitializeEmpty: window = %p", window); return reinterpret_cast<jlong>(window); }
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; }
static jstring getString_native(JNIEnv* env, jobject object, jint row, jint column) { int i; int32_t err; CursorWindow * window = GET_WINDOW(env, object); LOG_WINDOW("Getting string for %d,%d from %p", row, column, window); field_slot_t field; err = window->read_field_slot(row, column, &field); if (err != 0) { throwExceptionWithRowCol(env, row, column); return NULL; } uint8_t type = field.type; jint size = (jint)field.data.buffer.size; if (type == FIELD_TYPE_NULL) { return NULL; } else if (type == FIELD_TYPE_BLOB) { throw_sqlite3_exception(env, "Unable to convert BLOB to string"); return NULL; } else if (type == FIELD_TYPE_STRING) { jchar * buf = (jchar *)window->offsetToPtr(field.data.buffer.offset); jclass strClass = env->FindClass("java/lang/String"); jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V"); jstring encoding = env->NewStringUTF("UTF-16LE"); jbyteArray bytes = env->NewByteArray(size); env->SetByteArrayRegion(bytes, 0, size, (jbyte*)buf); return (jstring)env->NewObject(strClass, ctorID, bytes, encoding); } else if (type == FIELD_TYPE_INTEGER) { int64_t value; if (window->getLong(row, column, &value)) { char buf[32]; snprintf(buf, sizeof(buf), "%lld", value); return env->NewStringUTF((const char*)buf); } return NULL; } else if (type == FIELD_TYPE_FLOAT) { double value; if (window->getDouble(row, column, &value)) { char buf[32]; snprintf(buf, sizeof(buf), "%g", value); return env->NewStringUTF(buf); } return NULL; } }
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; }
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; }
static jstring nativeGetString(JNIEnv* env, jclass clazz, jlong windowPtr, jint row, jint column) { CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); LOG_WINDOW("Getting string for %d,%d from %p", row, column, window); CursorWindow::FieldSlot* fieldSlot = window->getFieldSlot(row, column); if (!fieldSlot) { throwExceptionWithRowCol(env, row, column); return NULL; } int32_t type = window->getFieldSlotType(fieldSlot); if (type == CursorWindow::FIELD_TYPE_STRING) { size_t sizeIncludingNull; const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull); if (sizeIncludingNull <= 1) { return gEmptyString; } // Convert to UTF-16 here instead of calling NewStringUTF. NewStringUTF // doesn't like UTF-8 strings with high codepoints. It actually expects // Modified UTF-8 with encoded surrogate pairs. String16 utf16(value, sizeIncludingNull - 1); return env->NewString(reinterpret_cast<const jchar*>(utf16.string()), utf16.size()); } else if (type == CursorWindow::FIELD_TYPE_INTEGER) { int64_t value = window->getFieldSlotValueLong(fieldSlot); char buf[32]; snprintf(buf, sizeof(buf), "%" PRId64, value); return env->NewStringUTF(buf); } else if (type == CursorWindow::FIELD_TYPE_FLOAT) { double value = window->getFieldSlotValueDouble(fieldSlot); char buf[32]; snprintf(buf, sizeof(buf), "%g", value); return env->NewStringUTF(buf); } else if (type == CursorWindow::FIELD_TYPE_NULL) { return NULL; } else if (type == CursorWindow::FIELD_TYPE_BLOB) { throw_sqlite3_exception(env, "Unable to convert BLOB to string"); return NULL; } else { throwUnknownTypeException(env, type); return NULL; } }
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 void native_init_empty(JNIEnv * env, jobject object, jboolean localOnly) { uint8_t * data; size_t size; CursorWindow * window; window = new CursorWindow(MAX_WINDOW_SIZE); if (!window) { jniThrowException(env, "java/lang/RuntimeException", "No memory for native window object"); return; } if (!window->initBuffer(localOnly)) { jniThrowException(env, "java/lang/IllegalStateException", "Couldn't init cursor window"); delete window; return; } LOG_WINDOW("native_init_empty: window = %p", window); SET_WINDOW(env, object, window); }
static jint nativeCreate(JNIEnv* env, jclass clazz, jstring nameObj, jint cursorWindowSize) { String8 name; if (nameObj) { const char* nameStr = env->GetStringUTFChars(nameObj, NULL); name.setTo(nameStr); env->ReleaseStringUTFChars(nameObj, nameStr); } if (name.size() == 0) { name.setTo("<unnamed>"); } CursorWindow* window; status_t status = CursorWindow::create(name, cursorWindowSize, &window); if (status || !window) { LOGE("Could not allocate CursorWindow '%s' of size %d due to error %d.", name.string(), cursorWindowSize, status); return 0; } LOG_WINDOW("nativeInitializeEmpty: window = %p", window); return reinterpret_cast<jint>(window); }
uint32_t CursorWindow::alloc(size_t requestedSize, bool aligned) { int32_t size; uint32_t padding; if (aligned) { // 4 byte alignment padding = 4 - (mFreeOffset & 0x3); } else { padding = 0; } size = requestedSize + padding; if (size > freeSpace()) { LOGE("need to grow: mSize = %d, size = %d, freeSpace() = %d, numRows = %d", mSize, size, freeSpace(), mHeader->numRows); // Only grow the window if the first row doesn't fit if (mHeader->numRows > 1) { LOGE("not growing since there are already %d row(s), max size %d", mHeader->numRows, mMaxSize); return 0; } // Find a new size that will fit the allocation int allocated = mSize - freeSpace(); int newSize = mSize + WINDOW_ALLOCATION_SIZE; while (size > (newSize - allocated)) { newSize += WINDOW_ALLOCATION_SIZE; if (newSize > mMaxSize) { LOGE("Attempting to grow window beyond max size (%d)", mMaxSize); return 0; } } LOG_WINDOW("found size %d", newSize); mSize = newSize; } uint32_t offset = mFreeOffset + padding; mFreeOffset += size; return offset; }
static void native_init_memory(JNIEnv * env, jobject object, jobject memObj) { sp<IMemory> memory = interface_cast<IMemory>(ibinderForJavaObject(env, memObj)); if (memory == NULL) { jniThrowException(env, "java/lang/IllegalStateException", "Couldn't get native binder"); return; } CursorWindow * window = new CursorWindow(); if (!window) { jniThrowException(env, "java/lang/RuntimeException", "No memory for native window object"); return; } if (!window->setMemory(memory)) { jniThrowException(env, "java/lang/RuntimeException", "No memory in memObj"); delete window; return; } LOG_WINDOW("native_init_memory: numRows = %d, numColumns = %d, window = %p", window->getNumRows(), window->getNumColumns(), window); SET_WINDOW(env, object, window); }