Disable pre-approval for Chinese users

as it is broken in many Chinese ROMs. In the future, we can gradually do extra checks for Chinese users and re-enable it for some of them.

This is just way easier than trying to detect Chinese ROMs which is a research project of its own.
This commit is contained in:
Torsten Grote
2026-05-21 09:13:37 -03:00
parent b8c702869f
commit 3e3fc846aa
4 changed files with 44 additions and 13 deletions

View File

@@ -1,15 +1,13 @@
package org.fdroid.download
import android.content.Context
import android.telephony.TelephonyManager
import androidx.core.os.LocaleListCompat
import dagger.hilt.android.qualifiers.ApplicationContext
import java.util.Locale
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.concurrent.atomics.ExperimentalAtomicApi
import org.fdroid.settings.SettingsConstants
import org.fdroid.settings.SettingsManager
import org.fdroid.utils.getCurrentLocation
@OptIn(ExperimentalAtomicApi::class)
@Singleton
@@ -24,7 +22,7 @@ constructor(
override fun cacheMirrorIpAddresses(
mirrorUrl: String,
ipv4Addresses: List<String>,
ipv6Addresses: List<String>
ipv6Addresses: List<String>,
) {
dnsWithCache.populateCacheWithStrings(mirrorUrl, ipv4Addresses, ipv6Addresses)
}
@@ -42,13 +40,5 @@ constructor(
return settingsManager.mirrorChooser == SettingsConstants.MirrorChooserValues.PreferForeign
}
override fun getCurrentLocation(): String {
val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
return tm.simCountryIso
?: tm.networkCountryIso
?: run {
val localeList = LocaleListCompat.getDefault()
localeList.get(0)?.country ?: Locale.getDefault().country
}
}
override fun getCurrentLocation(): String = getCurrentLocation(context)
}

View File

@@ -38,6 +38,7 @@ import org.fdroid.database.AppMetadata
import org.fdroid.index.v2.PackageVersion
import org.fdroid.ui.utils.isAppInForeground
import org.fdroid.utils.IoDispatcher
import org.fdroid.utils.isChina
@Singleton
class SessionInstallManager
@@ -105,6 +106,9 @@ constructor(
// should not be needed, so we say not supported
log.info { "Can do auto-update pre-approval for ${app.packageName} not needed." }
PreApprovalResult.NotSupported
} else if (isChina(context)) {
log.info { "Device is in China, pre-approval is broken." }
PreApprovalResult.NotSupported
} else if (SDK_INT >= 34) {
log.info { "Requesting pre-approval for ${app.packageName}..." }
try {

View File

@@ -1,6 +1,8 @@
package org.fdroid.utils
import android.content.Context
import android.telephony.TelephonyManager
import androidx.core.os.LocaleListCompat
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.text.SimpleDateFormat
@@ -30,6 +32,21 @@ fun getLogName(context: Context): String {
return "${context.packageName}-$time"
}
fun getCurrentLocation(context: Context): String {
val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
return tm.simCountryIso
?: tm.networkCountryIso
?: run {
val localeList = LocaleListCompat.getDefault()
localeList.get(0)?.country ?: Locale.getDefault().country
}
}
fun isChina(context: Context): Boolean {
val country = getCurrentLocation(context)
return country.equals("cn", ignoreCase = true)
}
val isFull: Boolean
get() = FLAVOR.startsWith("full")
val isBasic: Boolean

View File

@@ -10,6 +10,7 @@ import android.content.pm.PackageInstaller
import android.content.pm.PackageInstaller.Session
import android.content.pm.PackageManager
import android.os.Build.VERSION.SDK_INT
import android.telephony.TelephonyManager
import androidx.core.content.ContextCompat.registerReceiver
import io.mockk.Runs
import io.mockk.every
@@ -62,6 +63,7 @@ internal class SessionInstallManagerTest {
private val receiver: InstallBroadcastReceiver = mockk()
private val pendingIntent: PendingIntent = mockk()
private val session: Session = mockk()
private val telephonyManager: TelephonyManager = mockk(relaxed = true)
private val sessionId = 123
private val packageName = "com.example.app"
@@ -110,6 +112,7 @@ internal class SessionInstallManagerTest {
every { anyConstructed<Intent>().addFlags(any()) } returns mockk()
every { context.packageManager } returns packageManager
every { context.getSystemService(any()) } returns telephonyManager
every { packageManager.packageInstaller } returns packageInstaller
every { packageInstaller.mySessions } returns emptyList()
every { context.unregisterReceiver(any()) } just runs
@@ -604,4 +607,21 @@ internal class SessionInstallManagerTest {
listenerSlot.captured.invoke(receiver, packageInstallerResult, Intent("confirm"), msg)
}
}
@Test
fun `requestPreapproval not supported in China`(): Unit = runBlocking {
every { telephonyManager.simCountryIso } returns "CN"
every { telephonyManager.networkCountryIso } returns null
every { context.isAppInForeground() } returns true
val notSupportedResult =
sessionInstallManager.requestPreapproval(
app = appMetadata,
iconGetter = { null },
isUpdate = false,
version = appVersion,
canRequestUserConfirmationNow = true,
)
assertIs<PreApprovalResult.NotSupported>(notSupportedResult)
}
}