Skip to content

Potential ANR / main-thread blocking risk: openOutputStream(android.net.Uri) in ProfilesFragment.void exportProfiles$lambda$11() → ContentResolver-openOutputStream #3240

@venkyqz

Description

@venkyqz

Environment

  • App: Shadowsocks (com.github.shadowsocks)
  • Branch checked: master
  • File: mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt:474
  • Verified commit: ae28fd91931fe4d2d5aab044de9ceaf9ed07ad56

The Issue

While reviewing ProfilesFragment.void exportProfiles$lambda$11() → ContentResolver-openOutputStream, I noticed a potential main-thread blocking risk around android.content.ContentResolver#openOutputStream(android.net.Uri).

The latest source still performs the operation synchronously:

471:         if (data != null) ProfileManager.serializeToJson()?.let { profiles ->
472:             val activity = activity as MainActivity
473:             try {
474:                 activity.contentResolver.openOutputStream(data)!!.bufferedWriter().use {
475:                     it.write(profiles.toString(2))
476:                 }
477:             } catch (e: Exception) {
478:                 Timber.w(e)
479:                 activity.snackbar(e.readableMessage).show()

android.content.ContentResolver#openOutputStream(android.net.Uri) can block the calling thread while Android resolves a provider, opens a stream, performs database work, contacts account services, touches storage, or waits on remote I/O, depending on the API and URI/backend involved.

The Risk & Impact

If this method is reached from a UI-thread path, the operation can cause visible jank, StrictMode violations in debug builds, or an ANR when the provider/backend is slow, blocked, or unreachable. I am phrasing this as a source-level risk because I verified the current source pattern but did not run an on-device reproduction.

Current source path

<com.github.shadowsocks.ProfilesFragment: void exportProfiles$lambda$11(com.github.shadowsocks.ProfilesFragment,android.net.Uri)>
  -> android.content.ContentResolver#openOutputStream(android.net.Uri)

Next Steps / Verification Required

Please confirm whether this method can be reached from UI callbacks in the current app flow. If so, the blocking operation should be moved to the project’s existing background/IO pattern, with only UI updates posted back to the main thread.

Verification

I checked the latest upstream source at ae28fd91931fe4d2d5aab044de9ceaf9ed07ad56 and found the sensitive operation still present in mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt. This report is based on source-level inspection, not runtime reproduction.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions