Skip to content

Fix ANR risk: offload ContentResolver and ProfileManager I/O off the main thread#3241

Draft
Copilot wants to merge 2 commits intomasterfrom
copilot/fix-anr-risk-openoutputstream
Draft

Fix ANR risk: offload ContentResolver and ProfileManager I/O off the main thread#3241
Copilot wants to merge 2 commits intomasterfrom
copilot/fix-anr-risk-openoutputstream

Conversation

Copy link
Copy Markdown

Copilot AI commented Apr 28, 2026

ContentResolver.openOutputStream/openInputStream and ProfileManager.serializeToJson/createProfilesFromJson (SQLite) were called directly on the main thread inside ActivityResultCallback lambdas, risking ANR when the content provider or storage is slow.

Changes

  • ProfilesFragment (mobile): wrap importOrReplaceProfiles and exportProfiles callbacks in lifecycleScope.launch { withContext(Dispatchers.IO) { … } }; includes serializeToJson and createProfilesFromJson DB calls
  • MainPreferenceFragment (tv): same fix for replaceProfiles and exportProfiles callbacks
  • Added lifecycleScope, Dispatchers, launch, withContext imports to both files

UI error feedback (snackbar / Toast) stays on the main thread after withContext returns.

// Before
private val exportProfiles = registerForActivityResult(SaveJson) { data ->
    if (data != null) ProfileManager.serializeToJson()?.let { profiles ->
        activity.contentResolver.openOutputStream(data)!!.bufferedWriter().use {
            it.write(profiles.toString(2))
        }
    }
}

// After
private val exportProfiles = registerForActivityResult(SaveJson) { data ->
    if (data != null) lifecycleScope.launch {
        val activity = activity as MainActivity
        try {
            withContext(Dispatchers.IO) {
                ProfileManager.serializeToJson()?.let { profiles ->
                    activity.contentResolver.openOutputStream(data)!!.bufferedWriter().use {
                        it.write(profiles.toString(2))
                    }
                }
            }
        } catch (e: Exception) {
            Timber.w(e)
            activity.snackbar(e.readableMessage).show()
        }
    }
}

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.foojay.io
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java -Xmx64m -Xms64m -Dorg.gradle.appname=gradlew -classpath \"\" -jar /home/REDACTED/work/shadowsocks-android/shadowsocks-android/gradle/wrapper/gradle-wrapper.jar :mobile:compileDebugKotlin :tv:compileDebugKotlin (dns block)
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java -Xmx64m -Xms64m -Dorg.gradle.appname=gradlew -classpath \"\" -jar /home/REDACTED/work/shadowsocks-android/shadowsocks-android/gradle/wrapper/gradle-wrapper.jar :mobile:compileDebugKotlin :tv:compileDebugKotlin (dns block)
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java -Xmx64m -Xms64m -Dorg.gradle.appname=gradlew -classpath \"\" -jar /home/REDACTED/work/shadowsocks-android/shadowsocks-android/gradle/wrapper/gradle-wrapper.jar :mobile:compileDebugKotlin :tv:compileDebugKotlin -Dorg.gradle.java.home=/usr/lib/jvm/temurin-21-jdk-amd64 (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title [WIP] Fix potential ANR risk in exportProfiles function Fix ANR risk: offload ContentResolver and ProfileManager I/O off the main thread Apr 28, 2026
Copilot AI requested a review from madeye April 28, 2026 12:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants