mirror of
https://github.com/immich-app/immich.git
synced 2026-03-26 20:00:44 +03:00
conditional cronet
This commit is contained in:
@@ -109,6 +109,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation "com.squareup.okhttp3:okhttp:$okhttp_version"
|
implementation "com.squareup.okhttp3:okhttp:$okhttp_version"
|
||||||
|
implementation "com.google.net.cronet:cronet-okhttp:0.1.0"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||||
implementation "androidx.work:work-runtime-ktx:$work_version"
|
implementation "androidx.work:work-runtime-ktx:$work_version"
|
||||||
implementation "androidx.concurrent:concurrent-futures:$concurrent_version"
|
implementation "androidx.concurrent:concurrent-futures:$concurrent_version"
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ object SSLConfig {
|
|||||||
var trustManager: X509TrustManager? = null
|
var trustManager: X509TrustManager? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
var requiresCustomSSL: Boolean = false
|
||||||
|
private set
|
||||||
|
|
||||||
private val listeners = mutableListOf<() -> Unit>()
|
private val listeners = mutableListOf<() -> Unit>()
|
||||||
private var configHash: Int = 0
|
private var configHash: Int = 0
|
||||||
|
|
||||||
@@ -34,7 +37,8 @@ object SSLConfig {
|
|||||||
clientCertHash: Int
|
clientCertHash: Int
|
||||||
) {
|
) {
|
||||||
val newHash = computeHash(allowSelfSigned, serverHost, clientCertHash)
|
val newHash = computeHash(allowSelfSigned, serverHost, clientCertHash)
|
||||||
if (newHash == configHash && sslSocketFactory != null) {
|
val newRequiresCustomSSL = allowSelfSigned || keyManagers != null
|
||||||
|
if (newHash == configHash && sslSocketFactory != null && requiresCustomSSL == newRequiresCustomSSL) {
|
||||||
return // Config unchanged, skip
|
return // Config unchanged, skip
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,6 +47,7 @@ object SSLConfig {
|
|||||||
sslSocketFactory = sslContext.socketFactory
|
sslSocketFactory = sslContext.socketFactory
|
||||||
trustManager = trustManagers?.filterIsInstance<X509TrustManager>()?.firstOrNull()
|
trustManager = trustManagers?.filterIsInstance<X509TrustManager>()?.firstOrNull()
|
||||||
?: getDefaultTrustManager()
|
?: getDefaultTrustManager()
|
||||||
|
requiresCustomSSL = newRequiresCustomSSL
|
||||||
configHash = newHash
|
configHash = newHash
|
||||||
notifyListeners()
|
notifyListeners()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import android.graphics.ImageDecoder
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.CancellationSignal
|
import android.os.CancellationSignal
|
||||||
import app.alextran.immich.core.SSLConfig
|
import app.alextran.immich.core.SSLConfig
|
||||||
|
import com.google.net.cronet.okhttptransport.CronetCallFactory
|
||||||
import okhttp3.Call
|
import okhttp3.Call
|
||||||
import okhttp3.Callback
|
import okhttp3.Callback
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
@@ -16,6 +17,7 @@ import okhttp3.Response
|
|||||||
import okhttp3.Cache
|
import okhttp3.Cache
|
||||||
import okhttp3.ConnectionPool
|
import okhttp3.ConnectionPool
|
||||||
import okhttp3.Dispatcher
|
import okhttp3.Dispatcher
|
||||||
|
import org.chromium.net.CronetEngine
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
@@ -33,6 +35,7 @@ class RemoteImagesImpl(context: Context) : RemoteImageApi {
|
|||||||
private val lockedBitmaps = ConcurrentHashMap<Long, Bitmap>()
|
private val lockedBitmaps = ConcurrentHashMap<Long, Bitmap>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
appContext = context.applicationContext
|
||||||
cacheDir = context.cacheDir
|
cacheDir = context.cacheDir
|
||||||
client = buildClient()
|
client = buildClient()
|
||||||
}
|
}
|
||||||
@@ -47,8 +50,10 @@ class RemoteImagesImpl(context: Context) : RemoteImageApi {
|
|||||||
private val decodePool =
|
private val decodePool =
|
||||||
Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() / 2 + 1)
|
Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() / 2 + 1)
|
||||||
|
|
||||||
|
private var appContext: Context? = null
|
||||||
private var cacheDir: File? = null
|
private var cacheDir: File? = null
|
||||||
private var client: OkHttpClient? = null
|
private var client: Call.Factory? = null
|
||||||
|
private var cronetEngine: CronetEngine? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
System.loadLibrary("native_buffer")
|
System.loadLibrary("native_buffer")
|
||||||
@@ -62,15 +67,42 @@ class RemoteImagesImpl(context: Context) : RemoteImageApi {
|
|||||||
external fun unlockBitmapPixels(bitmap: Bitmap)
|
external fun unlockBitmapPixels(bitmap: Bitmap)
|
||||||
|
|
||||||
private fun invalidateClient() {
|
private fun invalidateClient() {
|
||||||
client?.let {
|
(client as? OkHttpClient)?.let {
|
||||||
it.dispatcher.cancelAll()
|
it.dispatcher.cancelAll()
|
||||||
it.connectionPool.evictAll()
|
it.connectionPool.evictAll()
|
||||||
it.cache?.close()
|
it.cache?.close()
|
||||||
}
|
}
|
||||||
|
cronetEngine?.shutdown()
|
||||||
|
cronetEngine = null
|
||||||
|
|
||||||
client = buildClient()
|
client = buildClient()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildClient(): OkHttpClient {
|
private fun buildClient(): Call.Factory {
|
||||||
|
val dir = cacheDir ?: throw IllegalStateException("Cache dir not set")
|
||||||
|
return if (SSLConfig.requiresCustomSSL) {
|
||||||
|
buildOkHttpClient(dir)
|
||||||
|
} else {
|
||||||
|
buildCronetClient(dir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildCronetClient(cacheDir: File): Call.Factory {
|
||||||
|
val ctx = appContext ?: throw IllegalStateException("Context not set")
|
||||||
|
val storageDir = File(cacheDir, "cronet").apply { mkdirs() }
|
||||||
|
val engine = CronetEngine.Builder(ctx)
|
||||||
|
.enableHttp2(true)
|
||||||
|
.enableQuic(true)
|
||||||
|
.enableBrotli(true)
|
||||||
|
.setStoragePath(storageDir.absolutePath)
|
||||||
|
.build()
|
||||||
|
.also { cronetEngine = it }
|
||||||
|
|
||||||
|
return CronetCallFactory.newBuilder(engine).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildOkHttpClient(cacheDir: File): OkHttpClient {
|
||||||
|
val dir = File(cacheDir, "okhttp")
|
||||||
val connectionPool = ConnectionPool(
|
val connectionPool = ConnectionPool(
|
||||||
maxIdleConnections = KEEP_ALIVE_CONNECTIONS,
|
maxIdleConnections = KEEP_ALIVE_CONNECTIONS,
|
||||||
keepAliveDuration = KEEP_ALIVE_DURATION_MINUTES,
|
keepAliveDuration = KEEP_ALIVE_DURATION_MINUTES,
|
||||||
@@ -81,10 +113,7 @@ class RemoteImagesImpl(context: Context) : RemoteImageApi {
|
|||||||
.dispatcher(Dispatcher().apply { maxRequestsPerHost = MAX_REQUESTS_PER_HOST })
|
.dispatcher(Dispatcher().apply { maxRequestsPerHost = MAX_REQUESTS_PER_HOST })
|
||||||
.connectionPool(connectionPool)
|
.connectionPool(connectionPool)
|
||||||
|
|
||||||
cacheDir?.let { dir ->
|
builder.cache(Cache((File(dir, "thumbnails")), CACHE_SIZE_BYTES))
|
||||||
val cacheSubdir = File(dir, "thumbnails")
|
|
||||||
builder.cache(Cache(cacheSubdir, CACHE_SIZE_BYTES))
|
|
||||||
}
|
|
||||||
|
|
||||||
val sslSocketFactory = SSLConfig.sslSocketFactory
|
val sslSocketFactory = SSLConfig.sslSocketFactory
|
||||||
val trustManager = SSLConfig.trustManager
|
val trustManager = SSLConfig.trustManager
|
||||||
|
|||||||
@@ -110,6 +110,9 @@ class RemoteImageApiDelegate: NSObject, URLSessionDataDelegate {
|
|||||||
defer { remove(requestId: requestId) }
|
defer { remove(requestId: requestId) }
|
||||||
|
|
||||||
if let error = error {
|
if let error = error {
|
||||||
|
if request.isCancelled || (error as NSError).code == NSURLErrorCancelled {
|
||||||
|
return request.completion(Self.cancelledResult)
|
||||||
|
}
|
||||||
return request.completion(.failure(error))
|
return request.completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,10 +34,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.16.0"
|
version: "1.17.0"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
|||||||
@@ -297,6 +297,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.2"
|
version: "1.1.2"
|
||||||
|
code_assets:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: code_assets
|
||||||
|
sha256: ae0db647e668cbb295a3527f0938e4039e004c80099dce2f964102373f5ce0b5
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.19.10"
|
||||||
code_builder:
|
code_builder:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -341,10 +349,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: cronet_http
|
name: cronet_http
|
||||||
sha256: "1b99ad5ae81aa9d2f12900e5f17d3681f3828629bb7f7fe7ad88076a34209840"
|
sha256: "1fff7f26ac0c4cda97fe2a9aa082494baee4775f167c27ba45f6c8e88571e3ab"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.0"
|
version: "1.7.0"
|
||||||
crop_image:
|
crop_image:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -381,10 +389,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: cupertino_http
|
name: cupertino_http
|
||||||
sha256: "72187f715837290a63479a5b0ae709f4fedad0ed6bd0441c275eceaa02d5abae"
|
sha256: "82cbec60c90bf785a047a9525688b6dacac444e177e1d5a5876963d3c50369e8"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0"
|
version: "2.4.0"
|
||||||
custom_lint:
|
custom_lint:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@@ -904,6 +912,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.1"
|
version: "0.8.1"
|
||||||
|
hooks:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: hooks
|
||||||
|
sha256: "5410b9f4f6c9f01e8ff0eb81c9801ea13a3c3d39f8f0b1613cda08e27eab3c18"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.20.5"
|
||||||
hooks_riverpod:
|
hooks_riverpod:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1105,10 +1121,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: jni
|
name: jni
|
||||||
sha256: d2c361082d554d4593c3012e26f6b188f902acd291330f13d6427641a92b3da1
|
sha256: "8706a77e94c76fe9ec9315e18949cc9479cc03af97085ca9c1077b61323ea12d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.14.2"
|
version: "0.15.2"
|
||||||
js:
|
js:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1269,6 +1285,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.4"
|
||||||
|
native_toolchain_c:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: native_toolchain_c
|
||||||
|
sha256: f8872ea6c7a50ce08db9ae280ca2b8efdd973157ce462826c82f3c3051d154ce
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.17.2"
|
||||||
native_video_player:
|
native_video_player:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1306,10 +1330,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: objective_c
|
name: objective_c
|
||||||
sha256: "9f034ba1eeca53ddb339bc8f4813cb07336a849cd735559b60cdc068ecce2dc7"
|
sha256: "55eb67ede1002d9771b3f9264d2c9d30bc364f0267bc1c6cc0883280d5f0c7cb"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.1.0"
|
version: "9.2.2"
|
||||||
octo_image:
|
octo_image:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -2235,5 +2259,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.3"
|
version: "3.1.3"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.9.0 <4.0.0"
|
dart: ">=3.10.0 <4.0.0"
|
||||||
flutter: ">=3.35.7"
|
flutter: ">=3.35.7"
|
||||||
|
|||||||
@@ -86,8 +86,8 @@ dependencies:
|
|||||||
uuid: ^4.5.1
|
uuid: ^4.5.1
|
||||||
wakelock_plus: ^1.3.0
|
wakelock_plus: ^1.3.0
|
||||||
worker_manager: ^7.2.7
|
worker_manager: ^7.2.7
|
||||||
cronet_http: ^1.5.0
|
cronet_http: ^1.7.0
|
||||||
cupertino_http: ^2.3.0
|
cupertino_http: ^2.4.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
auto_route_generator: ^9.0.0
|
auto_route_generator: ^9.0.0
|
||||||
|
|||||||
Reference in New Issue
Block a user