mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
The hybrid added in onReadCompleted reuses Cronet's ByteBuffer between reads to save a JNI wrap call when no grow is needed. That reuse breaks advance() — Cronet's position() is cumulative across reads, so the same K bytes get counted on every subsequent iteration. b.offset overshoots b.capacity, the reuse branch keeps firing on a now-empty buffer, and request.read() throws the original IllegalArgumentException again. Always pass a fresh wrap from wrapRemaining() so byteBuffer.position() reflects only this iteration's bytes. Same shape as the original PR had before the broken optimization was layered on top.
This commit is contained in:
@@ -265,18 +265,14 @@ private class CronetImageFetcher : ImageFetcher {
|
||||
byteBuffer: ByteBuffer
|
||||
) {
|
||||
try {
|
||||
val b = buffer!!
|
||||
b.advance(byteBuffer.position())
|
||||
// Reuse the caller-supplied ByteBuffer as long as we don't need to grow.
|
||||
// It already points at our native memory with position advanced past the
|
||||
// written bytes — Cronet can keep writing into the remaining tail.
|
||||
// Only when the buffer is full do we grow (which may realloc + move the
|
||||
// native pointer) and need a fresh wrap.
|
||||
val buf = if (b.offset == b.capacity) {
|
||||
b.ensureHeadroom()
|
||||
b.wrapRemaining()
|
||||
} else {
|
||||
byteBuffer
|
||||
// Always pass a fresh wrap so byteBuffer.position() represents only the
|
||||
// bytes Cronet wrote in this iteration. Reusing the caller-supplied
|
||||
// ByteBuffer breaks advance(): Cronet's position keeps accumulating
|
||||
// across reads, which would double-count previous iterations' bytes.
|
||||
val buf = buffer!!.run {
|
||||
advance(byteBuffer.position())
|
||||
ensureHeadroom()
|
||||
wrapRemaining()
|
||||
}
|
||||
request.read(buf)
|
||||
} catch (e: Exception) {
|
||||
|
||||
Reference in New Issue
Block a user