musikr: bubblewrap nativeinputstream

Try to avoid exceptions cascading and bringing down the app.
This commit is contained in:
Alexander Capehart 2025-01-18 09:58:05 -07:00
parent b81ecf44c0
commit 3aae8ea534
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
2 changed files with 70 additions and 20 deletions

View file

@ -34,11 +34,11 @@ JVMInputStream::JVMInputStream(JNIEnv *env, jobject inputStream) : env(env), inp
inputStreamIsOpenMethod = env->GetMethodID(inputStreamClass, "isOpen",
"()Z");
inputStreamSeekFromBeginningMethod = env->GetMethodID(inputStreamClass,
"seekFromBeginning", "(J)V");
"seekFromBeginning", "(J)Z");
inputStreamSeekFromCurrentMethod = env->GetMethodID(inputStreamClass,
"seekFromCurrent", "(J)V");
"seekFromCurrent", "(J)Z");
inputStreamSeekFromEndMethod = env->GetMethodID(inputStreamClass,
"seekFromEnd", "(J)V");
"seekFromEnd", "(J)Z");
inputStreamTellMethod = env->GetMethodID(inputStreamClass, "tell", "()J");
inputStreamLengthMethod = env->GetMethodID(inputStreamClass, "length",
"()J");
@ -58,6 +58,9 @@ TagLib::FileName JVMInputStream::name() const {
TagLib::ByteVector JVMInputStream::readBlock(size_t length) {
auto data = (jbyteArray) env->CallObjectMethod(inputStream,
inputStreamReadBlockMethod, length);
if (data == nullptr) {
throw std::runtime_error("Failed to read block, see logs");
}
jsize dataLength = env->GetArrayLength(data);
auto dataBytes = env->GetByteArrayElements(data, nullptr);
TagLib::ByteVector byteVector(reinterpret_cast<const char*>(dataBytes),
@ -89,19 +92,24 @@ bool JVMInputStream::isOpen() const {
void JVMInputStream::seek(TagLib::offset_t offset, Position p) {
auto joffset = static_cast<jlong>(std::llround(offset));
jboolean result;
switch (p) {
case Beginning:
env->CallVoidMethod(inputStream, inputStreamSeekFromBeginningMethod,
joffset);
result = env->CallBooleanMethod(inputStream,
inputStreamSeekFromBeginningMethod, joffset);
break;
case Current:
env->CallVoidMethod(inputStream, inputStreamSeekFromCurrentMethod,
joffset);
result = env->CallBooleanMethod(inputStream,
inputStreamSeekFromCurrentMethod, joffset);
break;
case End:
env->CallVoidMethod(inputStream, inputStreamSeekFromEndMethod, joffset);
result = env->CallBooleanMethod(inputStream,
inputStreamSeekFromEndMethod, joffset);
break;
}
if (!result) {
throw std::runtime_error("Failed to seek, see logs");
}
}
void JVMInputStream::clear() {
@ -110,11 +118,17 @@ void JVMInputStream::clear() {
TagLib::offset_t JVMInputStream::tell() const {
jlong jposition = env->CallLongMethod(inputStream, inputStreamTellMethod);
if (jposition == INT64_MIN) {
throw std::runtime_error("Failed to get position, see logs");
}
return static_cast<TagLib::offset_t>(jposition);
}
TagLib::offset_t JVMInputStream::length() {
jlong jlength = env->CallLongMethod(inputStream, inputStreamLengthMethod);
if (jlength == INT64_MIN) {
throw std::runtime_error("Failed to get length, see logs");
}
return static_cast<TagLib::offset_t>(jlength);
}

View file

@ -18,37 +18,73 @@
package org.oxycblt.musikr.metadata
import android.util.Log
import java.io.FileInputStream
import java.nio.ByteBuffer
internal class NativeInputStream(fis: FileInputStream) {
private val channel = fis.channel
fun readBlock(length: Long): ByteArray {
val buffer = ByteBuffer.allocate(length.toInt())
channel.read(buffer)
return buffer.array()
fun readBlock(length: Long): ByteArray? {
try {
val buffer = ByteBuffer.allocate(length.toInt())
channel.read(buffer)
return buffer.array()
} catch (e: Exception) {
Log.d("NativeInputStream", "Error reading block", e)
return null
}
}
fun isOpen(): Boolean {
return channel.isOpen
}
fun seekFromBeginning(offset: Long) {
channel.position(offset)
fun seekFromBeginning(offset: Long): Boolean {
try {
channel.position(offset)
return true
} catch (e: Exception) {
Log.d("NativeInputStream", "Error seeking from beginning", e)
return false
}
}
fun seekFromCurrent(offset: Long) {
channel.position(channel.position() + offset)
fun seekFromCurrent(offset: Long): Boolean {
try {
channel.position(channel.position() + offset)
return true
} catch (e: Exception) {
Log.d("NativeInputStream", "Error seeking from current", e)
return false
}
}
fun seekFromEnd(offset: Long) {
channel.position(channel.size() + offset)
fun seekFromEnd(offset: Long): Boolean {
try {
channel.position(channel.size() + offset)
return true
} catch (e: Exception) {
Log.d("NativeInputStream", "Error seeking from end", e)
return false
}
}
fun tell() = channel.position()
fun tell() =
try {
channel.position()
} catch (e: Exception) {
Log.d("NativeInputStream", "Error getting position", e)
Long.MIN_VALUE
}
fun length() = channel.size()
fun length() =
try {
channel.size()
} catch (e: Exception) {
Log.d("NativeInputStream", "Error getting length", e)
Long.MIN_VALUE
}
fun close() {
channel.close()