Skip to content

Commit 6daefd7

Browse files
committed
Added a separate thread to acquire the bitmap of the image and generate the thumbnail
1 parent d02e811 commit 6daefd7

File tree

1 file changed

+47
-25
lines changed

1 file changed

+47
-25
lines changed

data/src/main/java/org/cryptomator/data/cloud/crypto/CryptoImplDecorator.kt

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import android.content.Context
44
import android.graphics.Bitmap
55
import android.graphics.BitmapFactory
66
import android.media.ThumbnailUtils
7-
import android.os.Build
8-
import android.util.Size
97
import com.tomclaw.cache.DiskLruCache
8+
import okhttp3.internal.closeQuietly
109
import org.cryptomator.cryptolib.api.Cryptor
1110
import org.cryptomator.cryptolib.common.DecryptingReadableByteChannel
1211
import org.cryptomator.cryptolib.common.EncryptingWritableByteChannel
@@ -50,6 +49,9 @@ import java.util.Queue
5049
import java.util.UUID
5150
import java.util.function.Supplier
5251
import timber.log.Timber
52+
import java.io.PipedInputStream
53+
import java.io.PipedOutputStream
54+
import kotlin.concurrent.thread
5355

5456

5557
abstract class CryptoImplDecorator(
@@ -361,12 +363,30 @@ abstract class CryptoImplDecorator(
361363
val diskCache = cryptoFile.cloudFile.cloud?.type()?.let { getLruCacheFor(it) }
362364
val cacheKey = generateCacheKey(ciphertextFile)
363365
val genThumbnail = isGenerateThumbnailsEnabled(diskCache, cryptoFile.name)
364-
val decryptedTempFile : File
366+
var thumbnailBitmap : Bitmap? = null
367+
368+
val thumbnailWriter = PipedOutputStream()
369+
val thumbnailReader = PipedInputStream(thumbnailWriter)
370+
365371
try {
372+
// cloudContentRepository.read(file, encryptedTmpFile, encryptedData, ...)
373+
// file appena letto dalla rete, portato in cache ancora cifrato!
366374
val encryptedTmpFile = readToTmpFile(cryptoFile, ciphertextFile, progressAware)
367-
decryptedTempFile = File.createTempFile(encryptedTmpFile.nameWithoutExtension, ".tmp", internalCache)
368375

369-
val decryptedTempFileOutputStream = decryptedTempFile.outputStream()
376+
// TODO: reusable thread?
377+
// A thread pool is a managed collection of threads that runs tasks in parallel from a queue.
378+
// https://developer.android.com/develop/background-work/background-tasks/asynchronous/java-threads
379+
val t = thread(start = false, name = "S.AN-DRO") { // Simply A New Data Readable Output
380+
try {
381+
val bitmap = BitmapFactory.decodeStream(thumbnailReader) // wait for the full image
382+
thumbnailBitmap = ThumbnailUtils.extractThumbnail(bitmap, 100, 100)
383+
thumbnailReader.closeQuietly()
384+
} catch (e : Exception) {
385+
Timber.e("Bitmap generation crashed")
386+
}
387+
}
388+
389+
t.start()
370390
progressAware.onProgress(Progress.started(DownloadState.decryption(cryptoFile)))
371391
try {
372392
Channels.newChannel(FileInputStream(encryptedTmpFile)).use { readableByteChannel ->
@@ -378,34 +398,36 @@ abstract class CryptoImplDecorator(
378398
while (decryptingReadableByteChannel.read(buff).also { read = it } > 0) {
379399
buff.flip()
380400
data.write(buff.array(), 0, buff.remaining())
381-
decryptedTempFileOutputStream.write(buff.array(), 0, buff.remaining())
401+
thumbnailWriter.write(buff.array(), 0, buff.remaining())
382402

383403
decrypted += read.toLong()
404+
384405
progressAware
385-
.onProgress(
386-
Progress.progress(DownloadState.decryption(cryptoFile)) //
387-
.between(0) //
388-
.and(cleartextSize) //
389-
.withValue(decrypted)
390-
)
406+
.onProgress(
407+
Progress.progress(DownloadState.decryption(cryptoFile)) //
408+
.between(0) //
409+
.and(cleartextSize) //
410+
.withValue(decrypted)
411+
)
391412
}
392413
}
414+
thumbnailWriter.flush()
393415
}
394416
} finally {
395-
decryptedTempFileOutputStream.flush()
396-
decryptedTempFileOutputStream.close()
397417
encryptedTmpFile.delete()
418+
thumbnailWriter.closeQuietly()
398419
progressAware.onProgress(Progress.completed(DownloadState.decryption(cryptoFile)))
399420
}
421+
t.join() // wait the thread
422+
thumbnailReader.closeQuietly()
400423
} catch (e: IOException) {
401424
throw FatalBackendException(e)
402425
}
403426

404427
// store it in cloud-related LRU cache
405-
if(genThumbnail) {
406-
generateAndStoreThumbnail(diskCache, cacheKey, decryptedTempFile)
428+
if(genThumbnail && thumbnailBitmap != null) {
429+
generateAndStoreThumbnail(diskCache, cacheKey, thumbnailBitmap!!)
407430
}
408-
decryptedTempFile.delete()
409431
}
410432

411433
protected fun generateCacheKey(cloudFile: CloudFile) : String{
@@ -428,17 +450,17 @@ abstract class CryptoImplDecorator(
428450
isImageMediaType(fileName)
429451
}
430452

431-
private fun generateAndStoreThumbnail(cache: DiskLruCache?, cacheKey: String, thumbnailTmp: File) {
432-
// generate the Bitmap (in memory)
433-
val bitmap : Bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
434-
ThumbnailUtils.createImageThumbnail(thumbnailTmp, Size(100, 100), null)
435-
} else {
436-
ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(thumbnailTmp.path), 100, 100)
437-
}
453+
private fun generateAndStoreThumbnail(cache: DiskLruCache?, cacheKey: String, thumbnailBitmap: Bitmap){
454+
// // generate the Bitmap (in memory)
455+
// val bitmap : Bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
456+
// ThumbnailUtils.createImageThumbnail(thumbnailTmp, Size(100, 100), null)
457+
// } else {
458+
// ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(thumbnailTmp.path), 100, 100)
459+
// }
438460

439461
// write the thumbnail in a file (on disk)
440462
val thumbnailFile : File = File.createTempFile(UUID.randomUUID().toString(), ".thumbnail", internalCache)
441-
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, thumbnailFile.outputStream())
463+
thumbnailBitmap.compress(Bitmap.CompressFormat.JPEG, 100, thumbnailFile.outputStream())
442464

443465
try {
444466
cache?.let {

0 commit comments

Comments
 (0)