Skip to content

Potential Main thread blocking via synchronous ContentResolver query in ReaderFileDownloadManager #22959

@venkyqz

Description

@venkyqz

Description

Hi WordPress Android Team,

I’m a PhD student researching Android performance issues. My research group recently ran a static analysis scan for thread-affinity and main-thread blocking bugs, and our prototype flagged a potential issue in WordPress Android.

Checked target

  • APK-level caller: org.wordpress.android.ui.reader.ReaderFileDownloadManager#openDownloadedAttachment
  • Detected API: android.content.ContentResolver#query
  • Observed context: main/UI thread
  • Expected context: worker/background thread

What I found

The analyzer reported that the app call:

if (cursor.moveToFirst()) {

from a main/UI-thread path.

This is a synchronous content-provider operation. Depending on the provider and backing storage, it may involve Binder IPC, disk I/O, or document-provider work, so the reported UI path should not wait for it synchronously.

Verified bug trace

org.wordpress.android.ui.reader.ReaderFileDownloadManager#openDownloadedAttachment
  -> source location: WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderFileDownloadManager.kt:53
  -> source call: if (cursor.moveToFirst()) {
  -> ContentResolver dispatches synchronous provider/storage work
  -> backing provider may perform Binder, disk, or document-provider I/O before returning
  -> analyzer/source audit observed context: main/UI thread
  -> expected context: worker/background thread
  -> possible UI freeze / delayed response / jank / ANR risk

Source context used for verification:

51:         query.setFilterById(downloadId)
  52:         val cursor = downloadManager.query(query)
> 53:         if (cursor.moveToFirst()) {
  54:             val downloadStatus = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS))
  55:             val downloadLocalUri = cursor.getString(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_URI))

Why this matters

Running such an operation synchronously on the UI thread can potentially make WordPress Android feel frozen or delayed on slower devices, large datasets, or slow providers.

Possible fix

A possible fix is to move the blocking I/O, database, media, or system-service operation to a worker context and post only UI updates back to the main thread.

lifecycleScope.launch {
    val result = withContext(Dispatchers.IO) {
        performBlockingOperation()
    }

    renderResult(result)
}

Reference

-WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderFileDownloadManager.kt:53

Please confirm that you have searched existing issues in the repo.

  • Yes

Metadata

Metadata

Assignees

No one assigned

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions