static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fileDescriptor, jobject padding, jobject bitmapFactoryOptions) { NPE_CHECK_RETURN_ZERO(env, fileDescriptor); jint descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor); bool isPurgeable = optionsPurgeable(env, bitmapFactoryOptions); bool isShareable = optionsShareable(env, bitmapFactoryOptions); bool weOwnTheFD = false; if (isPurgeable && isShareable) { int newFD = ::dup(descriptor); if (-1 != newFD) { weOwnTheFD = true; descriptor = newFD; } } SkFDStream* stream = new SkFDStream(descriptor, weOwnTheFD); SkAutoUnref aur(stream); if (!stream->isValid()) { return NULL; } /* Restore our offset when we leave, so we can be called more than once with the same descriptor. This is only required if we didn't dup the file descriptor, but it is OK to do it all the time. */ AutoFDSeek as(descriptor); /* Allow purgeable iff we own the FD, i.e., in the puregeable and shareable case. */ return doDecode(env, stream, padding, bitmapFactoryOptions, weOwnTheFD); }
static jobject nativeNewInstanceFromFileDescriptor(JNIEnv* env, jobject clazz, jobject fileDescriptor, jboolean isShareable) { NPE_CHECK_RETURN_ZERO(env, fileDescriptor); jint descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor); SkStream *stream = NULL; struct stat fdStat; int newFD; if (fstat(descriptor, &fdStat) == -1) { doThrowIOE(env, "broken file descriptor"); return nullObjectReturn("fstat return -1"); } if (isShareable && S_ISREG(fdStat.st_mode) && (newFD = ::dup(descriptor)) != -1) { SkFDStream* fdStream = new SkFDStream(newFD, true); if (!fdStream->isValid()) { fdStream->unref(); return NULL; } stream = fdStream; } else { /* Restore our offset when we leave, so we can be called more than once with the same descriptor. This is only required if we didn't dup the file descriptor, but it is OK to do it all the time. */ AutoFDSeek as(descriptor); SkFDStream* fdStream = new SkFDStream(descriptor, false); if (!fdStream->isValid()) { fdStream->unref(); return NULL; } stream = buildSkMemoryStream(fdStream); fdStream->unref(); } return doBuildTileIndex(env, stream); }