KT-44089 Reflect Android SDK version to determine whether platform implementatoins are eligible

SDK version sanity check, suppress all reflection errors, duplicate SDK reflection code for more robustness
This commit is contained in:
Ilya Gorbunov
2021-11-26 16:56:28 +03:00
committed by TeamCityServer
parent fe77046fe4
commit eba6a4a000
2 changed files with 40 additions and 4 deletions
@@ -10,8 +10,28 @@ import kotlin.internal.PlatformImplementations
internal open class JDK7PlatformImplementations : PlatformImplementations() {
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
override fun addSuppressed(cause: Throwable, exception: Throwable) = (cause as java.lang.Throwable).addSuppressed(exception)
private object ReflectSdkVersion {
@JvmField
public val sdkVersion: Int? = try {
Class.forName("android.os.Build\$VERSION").getField("SDK_INT").get(null) as? Int
} catch (e: Throwable) {
null
}?.takeIf { it > 0 }
}
override fun getSuppressed(exception: Throwable): List<Throwable> = exception.suppressed.asList()
private fun sdkIsNullOrAtLeast(version: Int): Boolean = ReflectSdkVersion.sdkVersion == null || ReflectSdkVersion.sdkVersion >= version
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
override fun addSuppressed(cause: Throwable, exception: Throwable) =
if (sdkIsNullOrAtLeast(19))
(cause as java.lang.Throwable).addSuppressed(exception)
else
super.addSuppressed(cause, exception)
override fun getSuppressed(exception: Throwable): List<Throwable> =
if (sdkIsNullOrAtLeast(19))
exception.suppressed.asList()
else
super.getSuppressed(exception)
}
@@ -26,6 +26,19 @@ import kotlin.random.jdk8.PlatformThreadLocalRandom
internal open class JDK8PlatformImplementations : JDK7PlatformImplementations() {
// the same SDK version check as in the base class is duplicated here,
// to avoid having a non-public cross-module dependency
private object ReflectSdkVersion {
@JvmField
public val sdkVersion: Int? = try {
Class.forName("android.os.Build\$VERSION").getField("SDK_INT").get(null) as? Int
} catch (e: Throwable) {
null
}?.takeIf { it > 0 }
}
private fun sdkIsNullOrAtLeast(version: Int): Boolean = ReflectSdkVersion.sdkVersion == null || ReflectSdkVersion.sdkVersion >= version
override fun getMatchResultNamedGroup(matchResult: MatchResult, name: String): MatchGroup? {
val matcher = matchResult as? Matcher ?: throw UnsupportedOperationException("Retrieving groups by name is not supported on this platform.")
@@ -36,6 +49,9 @@ internal open class JDK8PlatformImplementations : JDK7PlatformImplementations()
null
}
override fun defaultPlatformRandom(): Random = PlatformThreadLocalRandom()
override fun defaultPlatformRandom(): Random =
// while ThreadLocalRandom is available since SDK 21 (as documented), it has bugs in the implementation,
// so we don't use it for the same reasons as why we don't use it in JDK7.
if (sdkIsNullOrAtLeast(24)) PlatformThreadLocalRandom() else super.defaultPlatformRandom()
}