Fix Let's Encrypt TLS on old API versions (#2489)

diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 30e3499..3c37d09 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -57,6 +57,7 @@
 mpandroidchart = "com.github.PhilJay:MPAndroidChart:_"
 nullaway = "com.uber.nullaway:nullaway:_"
 okhttp = "com.squareup.okhttp3:okhttp:_"
+okhttp-tls = "com.squareup.okhttp3:okhttp-tls:_"
 okio = "com.squareup.okio:okio:_"
 profileinstaller = "androidx.profileinstaller:profileinstaller:_"
 qrcodereaderview = "com.dlazaro66.qrcodereaderview:qrcodereaderview:_"
diff --git a/snapshot-tests/build.gradle b/snapshot-tests/build.gradle
index ba1e5a0..adde4e3 100644
--- a/snapshot-tests/build.gradle
+++ b/snapshot-tests/build.gradle
@@ -60,6 +60,7 @@
   implementation libs.compose.material
 
   implementation libs.okhttp
+  implementation libs.okhttp.tls
 
   androidTestImplementation libs.aws.android.sdk.s3
   androidTestImplementation(libs.aws.android.sdk.mobile.client) { transitive = true }
diff --git a/snapshot-tests/src/androidTest/java/com/airbnb/lottie/snapshots/utils/HappoSnapshotter.kt b/snapshot-tests/src/androidTest/java/com/airbnb/lottie/snapshots/utils/HappoSnapshotter.kt
index 82ea63a..ac613bd 100644
--- a/snapshot-tests/src/androidTest/java/com/airbnb/lottie/snapshots/utils/HappoSnapshotter.kt
+++ b/snapshot-tests/src/androidTest/java/com/airbnb/lottie/snapshots/utils/HappoSnapshotter.kt
@@ -6,6 +6,7 @@
 import android.util.Log
 import com.airbnb.lottie.L
 import com.airbnb.lottie.snapshots.BuildConfig
+import com.airbnb.lottie.snapshots.R
 import com.amazonaws.auth.BasicAWSCredentials
 import com.amazonaws.mobileconnectors.s3.transferutility.TransferObserver
 import com.amazonaws.mobileconnectors.s3.transferutility.TransferUtility
@@ -14,10 +15,20 @@
 import com.google.gson.JsonArray
 import com.google.gson.JsonElement
 import com.google.gson.JsonObject
-import kotlinx.coroutines.*
-import okhttp3.*
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import okhttp3.Call
+import okhttp3.Callback
+import okhttp3.Credentials
 import okhttp3.MediaType.Companion.toMediaType
+import okhttp3.OkHttpClient
+import okhttp3.Request
 import okhttp3.RequestBody.Companion.toRequestBody
+import okhttp3.Response
 import java.io.ByteArrayOutputStream
 import java.io.File
 import java.io.FileOutputStream
@@ -25,8 +36,14 @@
 import java.math.BigInteger
 import java.net.URLEncoder
 import java.nio.charset.Charset
+import java.security.KeyStore
 import java.security.MessageDigest
-import java.util.*
+import java.security.cert.CertificateFactory
+import java.security.cert.X509Certificate
+import java.util.UUID
+import javax.net.ssl.SSLContext
+import javax.net.ssl.TrustManagerFactory
+import javax.net.ssl.X509TrustManager
 import kotlin.coroutines.resume
 import kotlin.coroutines.resumeWithException
 import kotlin.coroutines.suspendCoroutine
@@ -60,7 +77,28 @@
     // private val reportNamePrefixes = listOf(System.currentTimeMillis().toString()).filter { it.isNotBlank() }
     private val reportNames = reportNamePrefixes.map { "$it-$androidVersion" }
 
-    private val okhttp = OkHttpClient()
+    private val okhttp by lazy {
+        // https://androiddev.social/@botteaap/112108241212116279
+        // https://letsencrypt.org/2023/07/10/cross-sign-expiration.html
+        // https://letsencrypt.org/certs/isrgrootx1.der
+        val ca: X509Certificate = context.resources.openRawResource(R.raw.isrgrootx1).use {
+            CertificateFactory.getInstance("X.509").generateCertificate(it) as X509Certificate
+        }
+
+        val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
+        keyStore.load(null, null)
+        keyStore.setCertificateEntry("ca", ca)
+
+        val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
+        trustManagerFactory.init(keyStore)
+
+        val sslContext: SSLContext = SSLContext.getInstance("TLS")
+        sslContext.init(null, trustManagerFactory.trustManagers, null)
+
+        OkHttpClient.Builder()
+            .sslSocketFactory(sslContext.socketFactory, trustManagerFactory.trustManagers[0] as X509TrustManager)
+            .build()
+    }
 
     private val transferUtility = TransferUtility.builder()
         .context(context)
@@ -155,4 +193,4 @@
             digest.update(this, 0, this.size)
             return BigInteger(1, digest.digest()).toString(16)
         }
-}
\ No newline at end of file
+}
diff --git a/snapshot-tests/src/main/res/raw/isrgrootx1.der b/snapshot-tests/src/main/res/raw/isrgrootx1.der
new file mode 100644
index 0000000..9d2132e
--- /dev/null
+++ b/snapshot-tests/src/main/res/raw/isrgrootx1.der
Binary files differ