anon-iclr-submission/benchname-bug-localization huggingface dataset:
Repository: square/leakcanary
Issue: RootViewWatcher onRootViewAdd crashed

### Description

```
android.content.res.Resources$NotFoundException: Resource ID #0x7f050008 type #0x5 is not valid
        at android.content.res.Resources.getBoolean(Resources.java:1088)
        at leakcanary.RootViewWatcher$listener$1.onRootViewAdded(RootViewWatcher.kt:49)
        at curtains.OnRootViewAddedListener$DefaultImpls.onRootViewsChanged(Listeners.kt:37)
        at leakcanary.RootViewWatcher$listener$1.onRootViewsChanged(RootViewWatcher.kt:43)
        at curtains.internal.RootViewsSpy$delegatingViewList$1.add(RootViewsSpy.kt:25)
        at curtains.internal.RootViewsSpy$delegatingViewList$1.add(RootViewsSpy.kt:23)
        at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:350)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:94)
        at android.app.Dialog.show(Dialog.java:329)
        at org.chromium.content.browser.input.SelectPopupDialog.show(SelectPopupDialog.java:146)
        at org.chromium.content.browser.input.SelectPopup.show(SelectPopup.java:162)
        at android.os.MessageQueue.nativePollOnce(Native Method)
        at android.os.MessageQueue.next(MessageQueue.java:326)
        at android.os.Looper.loop(Looper.java:165)
        at android.app.ActivityThread.main(ActivityThread.java:6821)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
```
### Steps to Reproduce

just intergration to Project 

**Expected behavior:**  be normal

### Version Information

* LeakCanary version: 2.7
* Android OS version: android 9.0
* Gradle version:6.1.1

### Additional Information




Changed files:
leakcanary-object-watcher-android/src/main/java/leakcanary/RootViewWatcher.kt

diff --git a/leakcanary-object-watcher-android/src/main/java/leakcanary/RootViewWatcher.kt b/leakcanary-object-watcher-android/src/main/java/leakcanary/RootViewWatcher.kt
index 4fbf1d535..c417e5a03 100644
--- a/leakcanary-object-watcher-android/src/main/java/leakcanary/RootViewWatcher.kt
+++ b/leakcanary-object-watcher-android/src/main/java/leakcanary/RootViewWatcher.kt
@@ -46,7 +46,12 @@ class RootViewWatcher(
         when (rootView.phoneWindow?.callback?.wrappedCallback) {
           // Activities are already tracked by ActivityWatcher
           is Activity -> false
-          is Dialog -> rootView.resources.getBoolean(R.bool.leak_canary_watcher_watch_dismissed_dialogs)
+          is Dialog -> {
+            // Use app context resources to avoid NotFoundException
+            // https://github.com/square/leakcanary/issues/2137
+            val resources = rootView.context.applicationContext.resources
+            resources.getBoolean(R.bool.leak_canary_watcher_watch_dismissed_dialogs)
+          }
           // Probably a DreamService
           else -> true
         }
Repository: square/leakcanary
Issue: InternalAppWatcher.install should check if the app is debuggable before installing DefaultCanaryLog()

https://github.com/square/leakcanary/blob/main/leakcanary-object-watcher-android/src/main/java/leakcanary/internal/InternalAppWatcher.kt#L65

We do this:

```
 SharkLog.logger = DefaultCanaryLog()
```

Which leads to LeakCanary logs in release builds iif you use app watcher in release builds (which is an ok thing to do)

Changed files:
leakcanary-object-watcher-android/src/main/java/leakcanary/internal/InternalAppWatcher.kt

diff --git a/leakcanary-object-watcher-android/src/main/java/leakcanary/internal/InternalAppWatcher.kt b/leakcanary-object-watcher-android/src/main/java/leakcanary/internal/InternalAppWatcher.kt
index 079e67769..177d433b7 100644
--- a/leakcanary-object-watcher-android/src/main/java/leakcanary/internal/InternalAppWatcher.kt
+++ b/leakcanary-object-watcher-android/src/main/java/leakcanary/internal/InternalAppWatcher.kt
@@ -36,6 +36,10 @@ internal object InternalAppWatcher {
     Handler(Looper.getMainLooper())
   }
 
+  private val isDebuggableBuild by lazy {
+    (application.applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE) != 0
+  }
+
   init {
     val internalLeakCanary = try {
       val leakCanaryListener = Class.forName("leakcanary.internal.InternalLeakCanary")
@@ -62,8 +66,10 @@ internal object InternalAppWatcher {
     if (this::application.isInitialized) {
       return
     }
-    SharkLog.logger = DefaultCanaryLog()
     InternalAppWatcher.application = application
+    if (isDebuggableBuild) {
+      SharkLog.logger = DefaultCanaryLog()
+    }
 
     val configProvider = { AppWatcher.config }
     ActivityDestroyWatcher.install(application, objectWatcher, configProvider)
Repository: square/leakcanary
Issue: Crash, heap dump  missing

HeapAnalyzer crashes because the heap dump file passed to the service didn't exist

```
leakcanary.HeapAnalysisException: java.lang.IllegalArgumentException: File does not exist: /storage/emulated/0/Download/leakcanary-com.squareup.development/f871e570-be04-4368-9621-c964c27671e8_pending.hprof
        at leakcanary.HeapAnalyzer.checkForLeaks(HeapAnalyzer.kt:93)
        at leakcanary.internal.HeapAnalyzerService.onHandleIntentInForeground(HeapAnalyzerService.kt:49)
        at leakcanary.internal.ForegroundService.onHandleIntent(ForegroundService.kt:55)
        at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:78)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.os.HandlerThread.run(HandlerThread.java:67)
Caused by: java.lang.IllegalArgumentException: File does not exist: /storage/emulated/0/Download/leakcanary-com.squareup.development/f871e570-be04-4368-9621-c964c27671e8_pending.hprof
        at leakcanary.HeapAnalyzer.checkForLeaks(HeapAnalyzer.kt:90)
        at leakcanary.internal.HeapAnalyzerService.onHandleIntentInForeground(HeapAnalyzerService.kt:49)
        at leakcanary.internal.ForegroundService.onHandleIntent(ForegroundService.kt:55)
        at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:78)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.os.HandlerThread.run(HandlerThread.java:67)
```

Not sure how this can happen. Worth noticing that 2 seconds before we were successfully parsing and handling a hprof (same? another one?)

The latest release of leakcanary does not block if an analysis is in progress, so there might be concurrency issue or old cleanup code that's too aggressive.

Changed files:
leakcanary-android-core/src/main/java/leakcanary/DefaultAnalysisResultListener.kt

diff --git a/leakcanary-android-core/src/main/java/leakcanary/DefaultAnalysisResultListener.kt b/leakcanary-android-core/src/main/java/leakcanary/DefaultAnalysisResultListener.kt
index f73f308c9..a1346543e 100644
--- a/leakcanary-android-core/src/main/java/leakcanary/DefaultAnalysisResultListener.kt
+++ b/leakcanary-android-core/src/main/java/leakcanary/DefaultAnalysisResultListener.kt
@@ -86,12 +86,14 @@ object DefaultAnalysisResultListener : AnalysisResultListener {
     val fileName = SimpleDateFormat("yyyy-MM-dd_HH-mm-ss_SSS'.hprof'", Locale.US).format(Date())
 
     val newFile = File(heapDumpFile.parent, fileName)
+    val lastModified = heapDumpFile.lastModified()
     val renamed = heapDumpFile.renameTo(newFile)
     if (!renamed) {
       CanaryLog.d(
           "Could not rename heap dump file %s to %s", heapDumpFile.path, newFile.path
       )
     }
+    newFile.setLastModified(lastModified)
     return newFile
   }
 }
\\ No newline at end of file
Repository: square/leakcanary
Issue: leakcanary code crash in some time when parsePathStrategy

### Description

Crash some time,but not always happen

### Steps to Reproduce
here is trace:

Caused by kotlin.KotlinNullPointerException
       at leakcanary.internal.LeakCanaryFileProvider$Companion.parsePathStrategy(LeakCanaryFileProvider.kt:458)
       at leakcanary.internal.LeakCanaryFileProvider$Companion.getPathStrategy(LeakCanaryFileProvider.kt:428)
       at leakcanary.internal.LeakCanaryFileProvider$Companion.access$getPathStrategy(LeakCanaryFileProvider.kt:366)
       at leakcanary.internal.LeakCanaryFileProvider.attachInfo(LeakCanaryFileProvider.kt:77)
       at android.app.ActivityThread.installProvider(ActivityThread.java:5811)
       at android.app.ActivityThread.installContentProviders(ActivityThread.java:5403)
       at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5342)
       at android.app.ActivityThread.-wrap2(ActivityThread.java)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1528)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:154)
       at android.app.ActivityThread.main(ActivityThread.java:6077)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)

**Expected behavior:** 
No crash

### Version Information

* LeakCanary version: 2.6
* Android OS version: 5.0
* Gradle version: don't remember

### Additional Information



Changed files:
leakcanary-android-core/src/main/java/leakcanary/internal/LeakCanaryFileProvider.kt

diff --git a/leakcanary-android-core/src/main/java/leakcanary/internal/LeakCanaryFileProvider.kt b/leakcanary-android-core/src/main/java/leakcanary/internal/LeakCanaryFileProvider.kt
index fbaa4b81c..052574763 100644
--- a/leakcanary-android-core/src/main/java/leakcanary/internal/LeakCanaryFileProvider.kt
+++ b/leakcanary-android-core/src/main/java/leakcanary/internal/LeakCanaryFileProvider.kt
@@ -455,7 +455,10 @@ internal class LeakCanaryFileProvider : ContentProvider() {
       val strat = SimplePathStrategy(authority)
 
       val info = context.packageManager
-        .resolveContentProvider(authority, PackageManager.GET_META_DATA)!!
+        .resolveContentProvider(authority, PackageManager.GET_META_DATA)
+        ?: throw IllegalArgumentException(
+          "Couldn't find meta-data for provider with authority $authority"
+        )
       val resourceParser = info.loadXmlMetaData(
         context.packageManager, META_DATA_FILE_PROVIDER_PATHS
       ) ?: throw IllegalArgumentException(
Repository: square/leakcanary
Issue: Before API 16, the sample would crash after heap analysis

### Description

``` java
12-10 15:49:03.205 18107-18129/com.example.leakcanary E/AndroidRuntime: FATAL EXCEPTION: IntentService[HeapAnalyzerService]
    java.lang.ClassCastException: android.database.sqlite.SQLiteDatabase cannot be cast to java.io.Closeable
        at leakcanary.DefaultOnHeapAnalyzedListener.onHeapAnalyzed(DefaultOnHeapAnalyzedListener.kt:46)
        at leakcanary.internal.HeapAnalyzerService.onHandleIntentInForeground(HeapAnalyzerService.kt:69)
        at leakcanary.internal.ForegroundService.onHandleIntent(ForegroundService.kt:55)
        at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.os.HandlerThread.run(HandlerThread.java:60)
```

### Steps to Reproduce

1. Downgrade `minSdkVersion` to 14 or 15 in `leakcanary-android-sample`'s build.gradle
2. Run on API 14 or 15 platform
2. Trigger 5 leaks
3. After heap analyzed, app will crash

**Expected behavior:** Run normally. (May all libraries `midSdkVersion` upgrade to API 16 would help)

### Version Information

* LeakCanary version: 2.5 or main branch
* Android OS version: 4.0.3
* Gradle version: 6.5

### Additional Information

Before 4.1.1, `SQLiteDatabase` did not implements `Closeable`.

``` java
public final class SQLiteDatabase extends SQLiteClosable {
    ...
}
```

* [android-4.0.4_r2.1](https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-4.0.4_r2.1/core/java/android/database/sqlite/SQLiteClosable.java)

```java
public abstract class SQLiteClosable {
    ...
}
```

* [android-4.1.1_r1](https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-4.1.1_r1/core/java/android/database/sqlite/SQLiteClosable.java)

```java
public abstract class SQLiteClosable implements Closeable {
    ...
}
```

Changed files:
leakcanary-android-core/src/main/java/leakcanary/DefaultOnHeapAnalyzedListener.kt

diff --git a/leakcanary-android-core/src/main/java/leakcanary/DefaultOnHeapAnalyzedListener.kt b/leakcanary-android-core/src/main/java/leakcanary/DefaultOnHeapAnalyzedListener.kt
index 6e73c32be..94890e4fe 100644
--- a/leakcanary-android-core/src/main/java/leakcanary/DefaultOnHeapAnalyzedListener.kt
+++ b/leakcanary-android-core/src/main/java/leakcanary/DefaultOnHeapAnalyzedListener.kt
@@ -43,9 +43,9 @@ class DefaultOnHeapAnalyzedListener private constructor(private val applicationP
   override fun onHeapAnalyzed(heapAnalysis: HeapAnalysis) {
     SharkLog.d { "\\u200B\\n${LeakTraceWrapper.wrap(heapAnalysis.toString(), 120)}" }
 
-    val id = LeaksDbHelper(application).writableDatabase.use { db ->
-      HeapAnalysisTable.insert(db, heapAnalysis)
-    }
+    val db = LeaksDbHelper(application).writableDatabase
+    val id = HeapAnalysisTable.insert(db, heapAnalysis)
+    db.releaseReference()
 
     val (contentTitle, screenToShow) = when (heapAnalysis) {
       is HeapAnalysisFailure -> application.getString(
Repository: square/leakcanary
Issue: Shark-CLI throwing java.lang.IllegalThreadStateException: process hasn't exited error on Mac-M1 chip machine

### Shark-CLI throwing java.lang.IllegalThreadStateException: process hasn't exited error on Mac-M1 chip machine.
Commd executing successfully after 6 to 7 tries.

### Steps to Reproduce

Run Shark-CLI -d <deviceID> -p <processID> analyze

Error:
Exception in thread "main" java.lang.IllegalThreadStateException: process hasn't exited
	at java.lang.UNIXProcess.exitValue(UNIXProcess.java:421)
	at shark.SharkCliCommand$Companion.runCommand(SharkCliCommand.kt:192)
	at shark.DumpProcessCommand$Companion.dumpHeap(DumpProcessCommand.kt:115)
	at shark.SharkCliCommand$Companion.retrieveHeapDumpFile(SharkCliCommand.kt:158)
	at shark.AnalyzeCommand.run(AnalyzeCommand.kt:16)
	at com.github.ajalt.clikt.parsers.Parser.parse(Parser.kt:139)
	at com.github.ajalt.clikt.parsers.Parser.parse(Parser.kt:14)
	at com.github.ajalt.clikt.core.CliktCommand.parse(CliktCommand.kt:215)
	at com.github.ajalt.clikt.core.CliktCommand.parse$default(CliktCommand.kt:212)
	at com.github.ajalt.clikt.core.CliktCommand.main(CliktCommand.kt:230)
	at com.github.ajalt.clikt.core.CliktCommand.main(CliktCommand.kt:253)
	at shark.MainKt.main(Main.kt:12)

**Expected behavior:**  Heap Analysis

### Version Information

* LeakCanary version: 2.9.1
* Android OS version: Android 10 and Android 11
* Gradle version:

### Additional Information

Any additional information, configuration or data that might be necessary to reproduce the issue.


Changed files:
shark/shark-cli/src/main/java/shark/SharkCliCommand.kt

diff --git a/shark/shark-cli/src/main/java/shark/SharkCliCommand.kt b/shark/shark-cli/src/main/java/shark/SharkCliCommand.kt
index 32d53d5a7..527368514 100644
--- a/shark/shark-cli/src/main/java/shark/SharkCliCommand.kt
+++ b/shark/shark-cli/src/main/java/shark/SharkCliCommand.kt
@@ -20,7 +20,6 @@ import java.io.File
 import java.io.PrintWriter
 import java.io.StringWriter
 import java.util.Properties
-import java.util.concurrent.TimeUnit.SECONDS
 
 class SharkCliCommand : CliktCommand(
   name = "shark-cli",
@@ -183,7 +182,7 @@ class SharkCliCommand : CliktCommand(
       val process = ProcessBuilder(*arguments)
         .directory(directory)
         .start()
-        .also { it.waitFor(10, SECONDS) }
+        .also { it.waitFor() }
 
       // See https://github.com/square/leakcanary/issues/1711
       // On Windows, the process doesn't always exit; calling to readText() makes it finish, so
@@ -211,4 +210,4 @@ class SharkCliCommand : CliktCommand(
       )
     }
   }
-}
\\ No newline at end of file
+}
Repository: square/leakcanary
Issue: LeakCanary stopped detecting leaked ViewModels

### Description

LeakCanary doesn't detect leaked ViewModels when using `lifecycle-viewmodel-ktx` dependency.
`androidx.lifecycle:lifecycle-viewmodel-ktx` (version 2.6.1)
The code it uses in `ViewModelClearedWatcher`  for retrieving the ViewModel map always throws, because the `-ktx` version uses `map` field, not `mMap`.

```
java.lang.NoSuchFieldException: No field mMap in class Landroidx/lifecycle/ViewModelStore; (declaration of 'androidx.lifecycle.ViewModelStore' appears in /...)
```

```Kotlin
private val viewModelMap: Map<String, ViewModel>? = try {
    val mMapField = ViewModelStore::class.java.getDeclaredField("mMap")
    mMapField.isAccessible = true
    @Suppress("UNCHECKED_CAST")
    mMapField[storeOwner.viewModelStore] as Map<String, ViewModel>
  } catch (ignored: Exception) {
    null
  }

```

### Version Information

* LeakCanary version: 2.1.0
* Android OS version: SDK 30
* Gradle version: 8.0.2


Changed files:
leakcanary-object-watcher-android-androidx/src/main/java/leakcanary/internal/ViewModelClearedWatcher.kt

diff --git a/leakcanary-object-watcher-android-androidx/src/main/java/leakcanary/internal/ViewModelClearedWatcher.kt b/leakcanary-object-watcher-android-androidx/src/main/java/leakcanary/internal/ViewModelClearedWatcher.kt
index 5da492da2..1fc4e5738 100644
--- a/leakcanary-object-watcher-android-androidx/src/main/java/leakcanary/internal/ViewModelClearedWatcher.kt
+++ b/leakcanary-object-watcher-android-androidx/src/main/java/leakcanary/internal/ViewModelClearedWatcher.kt
@@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModelStore
 import androidx.lifecycle.ViewModelStoreOwner
 import leakcanary.ReachabilityWatcher
 import leakcanary.internal.ViewModelClearedWatcher.Companion.install
+import shark.SharkLog
 
 /**
  * [AndroidXFragmentDestroyWatcher] calls [install] to add a spy [ViewModel] in every
@@ -23,11 +24,19 @@ internal class ViewModelClearedWatcher(
   // however that was added in 2.1.0 and we support AndroidX first stable release. viewmodel-2.0.0
   // does not have ViewModelStore#keys. All versions currently have the mMap field.
   private val viewModelMap: Map<String, ViewModel>? = try {
-    val mMapField = ViewModelStore::class.java.getDeclaredField("mMap")
-    mMapField.isAccessible = true
+    val storeClass = ViewModelStore::class.java
+    val mapField = try {
+      storeClass.getDeclaredField("map")
+    } catch (exception: NoSuchFieldException) {
+      // Field name changed from mMap to map with Kotlin conversion
+      // https://cs.android.com/androidx/platform/frameworks/support/+/8aa6ca1c924ab10d263b21b99b8790d5f0b50cc6
+      storeClass.getDeclaredField("mMap")
+    }
+    mapField.isAccessible = true
     @Suppress("UNCHECKED_CAST")
-    mMapField[storeOwner.viewModelStore] as Map<String, ViewModel>
+    mapField[storeOwner.viewModelStore] as Map<String, ViewModel>
   } catch (ignored: Exception) {
+    SharkLog.d(ignored) { "Could not find ViewModelStore map of view models" }
     null
   }
Repository: square/leakcanary
Issue: ThrowingCancelableFileSourceProvider crash

### Description

We're receiving crashlytics reports on Samsung devices following updating from version 2.8.1 to 2.9.1

### Version Information

* LeakCanary version: 2.9.1
* Android OS version: 11/12
* Gradle version: 7.2

### Additional Information

```
Fatal Exception: java.io.IOException
close failed: EACCES (Permission denied)
libcore.io.IoBridge.closeAndSignalBlockedThreads (IoBridge.java:315)

java.nio.channels.spi.AbstractInterruptibleChannel.close (AbstractInterruptibleChannel.java:116)
shark.ThrowingCancelableFileSourceProvider$openRandomAccessSource$1.close (ThrowingCancelableFileSourceProvider.kt:43)
shark.ConstantMemoryMetricsDualSourceProvider$openRandomAccessSource$1.close (ConstantMemoryMetricsDualSourceProvider.kt:63)
shark.RandomAccessHprofReader.close (RandomAccessHprofReader.kt:51)
shark.HprofHeapGraph.close (HprofHeapGraph.kt:230)
kotlin.io.CloseableKt.closeFinally (Closeable.kt:57)
leakcanary.internal.AndroidDebugHeapAnalyzer.analyzeHeap (AndroidDebugHeapAnalyzer.kt:155)
leakcanary.internal.AndroidDebugHeapAnalyzer.runAnalysisBlocking (AndroidDebugHeapAnalyzer.kt:59)
leakcanary.internal.AndroidDebugHeapAnalyzer.runAnalysisBlocking$default (AndroidDebugHeapAnalyzer.kt:46)
leakcanary.BackgroundThreadHeapAnalyzer$onEvent$1.run (BackgroundThreadHeapAnalyzer.kt:24)
```

Changed files:
shark-hprof/src/main/java/shark/ThrowingCancelableFileSourceProvider.kt

diff --git a/shark-hprof/src/main/java/shark/ThrowingCancelableFileSourceProvider.kt b/shark-hprof/src/main/java/shark/ThrowingCancelableFileSourceProvider.kt
index 05a81049f..3f40c68ab 100644
--- a/shark-hprof/src/main/java/shark/ThrowingCancelableFileSourceProvider.kt
+++ b/shark-hprof/src/main/java/shark/ThrowingCancelableFileSourceProvider.kt
@@ -1,6 +1,7 @@
 package shark
 
 import java.io.File
+import java.io.IOException
 import okio.Buffer
 import okio.BufferedSource
 import okio.Okio
@@ -40,7 +41,13 @@ class ThrowingCancelableFileSourceProvider(
         return channel.transferTo(position, byteCount, sink)
       }
 
-      override fun close() = channel.close()
+      override fun close() {
+        try {
+          channel.close()
+        } catch (ignored: Throwable) {
+          SharkLog.d(ignored) { "Failed to close file, ignoring" }
+        }
+      }
     }
   }
 }
Repository: square/leakcanary
Issue: Crash when exploring an HeapDump

### Description

Got a crash with 2.9.1 but can't reproduce again for now. Reporting in case there's something to look into.

### Steps to Reproduce

Not 100% sure was while navigating inside an HeapDump or while leaving the heap dump screen. Can't reproduce despite many attempts.

### Version Information

* LeakCanary version: 2.9.1
* Android OS version: 12
* Gradle version: 7.4.2

### Additional Information
Log:

```
java.lang.IllegalStateException: Already closed
	at leakcanary.internal.activity.db.ScopedLeaksDb$DbOpener.checkClosed(ScopedLeaksDb.kt:69)
	at leakcanary.internal.activity.db.ScopedLeaksDb$DbOpener.getWritableDatabase(ScopedLeaksDb.kt:51)
	at leakcanary.internal.activity.db.Db$execute$1.invoke(Db.kt:35)
	at leakcanary.internal.activity.db.Db$execute$1.invoke(Db.kt:9)
	at leakcanary.internal.activity.db.Io$execute$2.invoke(Io.kt:44)
	at leakcanary.internal.activity.db.Io$execute$2.run(Io.kt:10)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
	at java.lang.Thread.run(Thread.java:920)
```


Changed files:
leakcanary-android-core/src/main/java/leakcanary/internal/activity/db/Db.kt

diff --git a/leakcanary-android-core/src/main/java/leakcanary/internal/activity/db/Db.kt b/leakcanary-android-core/src/main/java/leakcanary/internal/activity/db/Db.kt
index 87ca446eb..392fa6579 100644
--- a/leakcanary-android-core/src/main/java/leakcanary/internal/activity/db/Db.kt
+++ b/leakcanary-android-core/src/main/java/leakcanary/internal/activity/db/Db.kt
@@ -45,6 +45,7 @@ internal object Db {
     // Closing on the serial IO thread to ensure we don't close while using the db.
     Io.execute {
       dbHelper?.close()
+      dbHelper = null
     }
   }
 }
Repository: square/leakcanary
Issue: BackgroundListener$checkAppInBackground scheduled N times

Was just looking at a random Espresso report and noticed this:

```
Looper (main, tid 1) {5edfd65}
  Message 0: ...
  Message 1: { when=+1s743ms callback=leakcanary.internal.BackgroundListener$checkAppInBackground$1 target=android.os.Handler }
  Message 2: { when=+2s807ms callback=leakcanary.internal.BackgroundListener$checkAppInBackground$1 target=android.os.Handler }
  Message 3: { when=+2s807ms callback=leakcanary.internal.BackgroundListener$checkAppInBackground$1 target=android.os.Handler }
  Message 4: { when=+2s807ms callback=leakcanary.internal.BackgroundListener$checkAppInBackground$1 target=android.os.Handler }
  Message 5: { when=+2s807ms callback=leakcanary.internal.BackgroundListener$checkAppInBackground$1 target=android.os.Handler }
  Message 6: { when=+3s742ms callback=leakcanary.internal.BackgroundListener$checkAppInBackground$1 target=android.os.Handler }
  Message 7: { when=+3s742ms callback=leakcanary.internal.BackgroundListener$checkAppInBackground$1 target=android.os.Handler }
  Message 8: { when=+3s742ms callback=leakcanary.internal.BackgroundListener$checkAppInBackground$1 target=android.os.Handler }
  Message 9: { when=+3s743ms callback=leakcanary.internal.BackgroundListener$checkAppInBackground$1 target=android.os.Handler }
  Message 10: { when=+4s718ms callback=leakcanary.internal.BackgroundListener$checkAppInBackground$1 target=android.os.Handler }
  Message 11: { when=+4s847ms callback=leakcanary.internal.BackgroundListener$checkAppInBackground$1 target=android.os.Handler }
  Message 12: { when=+4s847ms callback=leakcanary.internal.BackgroundListener$checkAppInBackground$1 target=android.os.Handler }
  Message 13: { when=+4s847ms callback=leakcanary.internal.BackgroundListener$checkAppInBackground$1 target=android.os.Handler }
  Message 14: { when=+4s848ms callback=leakcanary.internal.BackgroundListener$checkAppInBackground$1 target=android.os.Handler }
  ```
  
  
  

Changed files:
leakcanary-android-release/src/main/java/leakcanary/internal/BackgroundListener.kt

diff --git a/leakcanary-android-release/src/main/java/leakcanary/internal/BackgroundListener.kt b/leakcanary-android-release/src/main/java/leakcanary/internal/BackgroundListener.kt
index d9e997398..76a5033e5 100644
--- a/leakcanary-android-release/src/main/java/leakcanary/internal/BackgroundListener.kt
+++ b/leakcanary-android-release/src/main/java/leakcanary/internal/BackgroundListener.kt
@@ -44,6 +44,7 @@ internal class BackgroundListener(
   fun uninstall(application: Application) {
     application.unregisterActivityLifecycleCallbacks(this)
     updateBackgroundState(appInBackgroundNow = false)
+    mainHandler.removeCallbacks(checkAppInBackground)
   }
 
   override fun onActivityPaused(activity: Activity) {
@@ -60,4 +61,4 @@ internal class BackgroundListener(
     private const val BACKGROUND_DELAY_MS = 1000L
     private const val BACKGROUND_REPEAT_DELAY_MS = 5000L
   }
-}
\\ No newline at end of file
+}
Repository: square/leakcanary
Issue: Remove Message leak fix / flushing

I read somewhere that Android 12 (?) fixed the Message leak issues. Need to confirm / find sources (slack asg perf, link to a gdoc? gchat?) and then check if it's fixed and if yes we can remove the flushing fix (and write a blog on this)

Changed files:
plumber-android-core/src/main/java/leakcanary/AndroidLeakFixes.kt, shark-android/src/main/java/shark/AndroidReferenceMatchers.kt

diff --git a/plumber-android-core/src/main/java/leakcanary/AndroidLeakFixes.kt b/plumber-android-core/src/main/java/leakcanary/AndroidLeakFixes.kt
index 72a70f508..d11df4959 100644
--- a/plumber-android-core/src/main/java/leakcanary/AndroidLeakFixes.kt
+++ b/plumber-android-core/src/main/java/leakcanary/AndroidLeakFixes.kt
@@ -150,6 +150,9 @@ enum class AndroidLeakFixes {
    */
   FLUSH_HANDLER_THREADS {
     override fun apply(application: Application) {
+      if (SDK_INT >= 31) {
+        return
+      }
       val flushedThreadIds = mutableSetOf<Int>()
       // Don't flush the backgroundHandler's thread, we're rescheduling all the time anyway.
       flushedThreadIds += (backgroundHandler.looper.thread as HandlerThread).threadId
diff --git a/shark-android/src/main/java/shark/AndroidReferenceMatchers.kt b/shark-android/src/main/java/shark/AndroidReferenceMatchers.kt
index 8d77938bb..d3be3c4f8 100644
--- a/shark-android/src/main/java/shark/AndroidReferenceMatchers.kt
+++ b/shark-android/src/main/java/shark/AndroidReferenceMatchers.kt
@@ -180,12 +180,14 @@ enum class AndroidReferenceMatchers {
         + " The combination of these two things creates a high potential for memory leaks as soon"
         + " as you use dialogs. These memory leaks might be temporary, but some handler threads"
         + " sleep for a long time."
-        + " To fix this, you could post empty messages to the idle handler threads from time to"
-        + " time. This won't be easy because you cannot access all handler threads, but a library"
-        + " that is widely used should consider doing this for its own handler threads. This leaks"
-        + " has been shown to happen in both Dalvik and ART.")
+        + " This leak is fixed by AndroidLeakFixes.FLUSH_HANDLER_THREADS in plumber-android."
+        + " Bug report: https://issuetracker.google.com/issues/146144484"
+        + " Fixed in Android 12: https://cs.android.com/android/_/android/platform/frameworks/base"
+        + "/+/d577e728e9bccbafc707af3060ea914caa73c14f")
 
-      references += instanceFieldLeak("android.os.Message", "obj", description)
+      references += instanceFieldLeak("android.os.Message", "obj", description) {
+        sdkInt < 31
+      }
     }
   },
Repository: square/leakcanary
Issue: LeakCanary RuntimeException when there is no label set in AndroidManifest

### Description

When there is no label attribute set in AndroidManifest <application> tag, LeakCanary crashes on application startup.

### Steps to Reproduce

Any project without label attribute in <application> AndroidManifest

1. Make sure you don't have label attribute set
2. First install of the app without the label attribute
3. start the app 
4. RuntimeException 

**Expected behavior:** Expect LeakCanary to not crash

### Version Information

* LeakCanary version: issue first happened on beta-1, issue not happening on alpha-3 version
* Android OS version: 8.0.0
* Gradle version: gradle-5.4.1


Changed files:
leakcanary-android-core/src/main/java/leakcanary/internal/InternalLeakCanary.kt

diff --git a/leakcanary-android-core/src/main/java/leakcanary/internal/InternalLeakCanary.kt b/leakcanary-android-core/src/main/java/leakcanary/internal/InternalLeakCanary.kt
index cf17596a2..431d34345 100644
--- a/leakcanary-android-core/src/main/java/leakcanary/internal/InternalLeakCanary.kt
+++ b/leakcanary-android-core/src/main/java/leakcanary/internal/InternalLeakCanary.kt
@@ -158,16 +158,10 @@ internal object InternalLeakCanary : (Application) -> Unit, OnObjectRetainedList
       longLabel = leakActivityLabel
       shortLabel = leakActivityLabel
     } else {
-
       val firstLauncherActivityLabel = if (firstMainActivity.labelRes != 0) {
         application.getString(firstMainActivity.labelRes)
       } else {
-        val applicationInfo = application.applicationInfo
-        if (applicationInfo.labelRes != 0) {
-          application.getString(applicationInfo.labelRes)
-        } else {
-          applicationInfo.nonLocalizedLabel.toString()
-        }
+        application.packageManager.getApplicationLabel(application.applicationInfo)
       }
       val fullLengthLabel = "$firstLauncherActivityLabel $leakActivityLabel"
       // short label should be under 10 and long label under 25
Repository: square/leakcanary
Issue: Invalid Hprof? Found unknown object id

I'm getting these messages when LeakCanary analyze the heap dump.

```
Invalid Hprof? Found unknown object id 348267312
Invalid Hprof? Found unknown object id 348783744
```

It doesn't appear all the times, but it's kind of easy to reproduce it.

It seems that it's not a major problem because Leak Canary shows me all the leaks and it's paths but it's kind of strange to get that messages in a reproducible way, for this reason I'm reporting it.

I attach the hprof: [2019-09-11_15-17-22_658.hprof.zip](https://github.com/square/leakcanary/files/3601087/2019-09-11_15-17-22_658.hprof.zip)

### Version Information

* LeakCanary version: 2.0.0-beta-3
* Android OS version: Android 9 (Emulator)
* Gradle version: 5.5

Changed files:
shark/src/main/java/shark/internal/PathFinder.kt

diff --git a/shark/src/main/java/shark/internal/PathFinder.kt b/shark/src/main/java/shark/internal/PathFinder.kt
index 30bb3bfe7..aeb344b89 100644
--- a/shark/src/main/java/shark/internal/PathFinder.kt
+++ b/shark/src/main/java/shark/internal/PathFinder.kt
@@ -329,13 +329,7 @@ internal class PathFinder(
         .filter { gcRoot ->
           // GC roots sometimes reference objects that don't exist in the heap dump
           // See https://github.com/square/leakcanary/issues/1516
-          val objectExists = graph.objectExists(gcRoot.id)
-          if (!objectExists) {
-            SharkLog.d {
-              "${gcRoot::class.java.simpleName} gc root ignored because it's pointing to unknown object @${gcRoot.id}"
-            }
-          }
-          objectExists
+          graph.objectExists(gcRoot.id)
         }
         .map { graph.findObjectById(it.id) to it }
         .sortedWith(Comparator { (graphObject1, root1), (graphObject2, root2) ->
@@ -449,13 +443,7 @@ internal class PathFinder(
   ) {
     val record = objectArray.readRecord()
     val nonNullElementIds = record.elementIds.filter { objectId ->
-      objectId != ValueHolder.NULL_REFERENCE && graph.objectExists(objectId).apply {
-        if (!this) {
-          // dalvik.system.PathClassLoader.runtimeInternalObjects references objects which don't
-          // otherwise exist in the heap dump.
-          SharkLog.d { "Invalid Hprof? Found unknown object id $objectId" }
-        }
-      }
+      objectId != ValueHolder.NULL_REFERENCE && graph.objectExists(objectId)
     }
     nonNullElementIds.forEachIndexed { index, elementId ->
       if (computeRetainedHeapSize) {
Repository: square/leakcanary
Issue: FATAL EXCEPTION: IntentService[HeapAnalyzerService]

### Description

My App runs well before 'debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.0-beta-3', but it crash after that.
The application using kotlin and androidx, enable multiple-dex.

```
    --------- beginning of crash
10723-10859/com.wizarpos.nigeriapay E/AndroidRuntime: FATAL EXCEPTION: IntentService[HeapAnalyzerService]
    kotlin.TypeCastException: null cannot be cast to non-null type java.io.File
        at leakcanary.internal.HeapAnalyzerService.onHandleIntentInForeground(HeapAnalyzerService.kt:46)
        at leakcanary.internal.ForegroundService.onHandleIntent(ForegroundService.kt:55)
        at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:66)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:148)
        at android.os.HandlerThread.run(HandlerThread.java:61)
```


Changed files:
leakcanary-android-core/src/main/java/leakcanary/internal/HeapAnalyzerService.kt

diff --git a/leakcanary-android-core/src/main/java/leakcanary/internal/HeapAnalyzerService.kt b/leakcanary-android-core/src/main/java/leakcanary/internal/HeapAnalyzerService.kt
index ef41a1857..131b9cde7 100644
--- a/leakcanary-android-core/src/main/java/leakcanary/internal/HeapAnalyzerService.kt
+++ b/leakcanary-android-core/src/main/java/leakcanary/internal/HeapAnalyzerService.kt
@@ -37,10 +37,11 @@ internal class HeapAnalyzerService : ForegroundService(
 ), OnAnalysisProgressListener {
 
   override fun onHandleIntentInForeground(intent: Intent?) {
-    if (intent == null) {
-      SharkLog.d { "HeapAnalyzerService received a null intent, ignoring." }
+    if (intent == null || !intent.hasExtra(HEAPDUMP_FILE_EXTRA)) {
+      SharkLog.d { "HeapAnalyzerService received a null or empty intent, ignoring." }
       return
     }
+
     // Since we're running in the main process we should be careful not to impact it.
     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)
     val heapDumpFile = intent.getSerializableExtra(HEAPDUMP_FILE_EXTRA) as File
@@ -89,7 +90,7 @@ internal class HeapAnalyzerService : ForegroundService(
       startForegroundService(context, intent)
     }
 
-    fun startForegroundService(
+    private fun startForegroundService(
       context: Context,
       intent: Intent
     ) {
Repository: square/leakcanary
Issue: Resource$NotFoundException in plug-in project

### Description

I have the same issue with #1385:

```
android.content.res.Resources$NotFoundException: Resource ID #0x7f0b03a0
    at android.content.res.ResourcesImpl.getValue(ResourcesImpl.java:237)
    at android.content.res.Resources.getDimensionPixelSize(Resources.java:745)
    at leakcanary.internal.AndroidHeapDumper$showToast$1.run(AndroidHeapDumper.kt:95)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7678)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
```

val iconSize = resumedActivity.resources.getDimensionPixelSize( R.dimen.leak_canary_toast_icon_size )

'R.dimen.leak_canary_toast_icon_size ' can not found in a plugin activity


### Version Information

* LeakCanary version: 2.5
* Android OS version: 10
* Gradle version: 4.4




Changed files:
leakcanary-android-core/src/main/java/leakcanary/internal/AndroidHeapDumper.kt

diff --git a/leakcanary-android-core/src/main/java/leakcanary/internal/AndroidHeapDumper.kt b/leakcanary-android-core/src/main/java/leakcanary/internal/AndroidHeapDumper.kt
index fe6a0aa4f..499b90313 100644
--- a/leakcanary-android-core/src/main/java/leakcanary/internal/AndroidHeapDumper.kt
+++ b/leakcanary-android-core/src/main/java/leakcanary/internal/AndroidHeapDumper.kt
@@ -92,7 +92,8 @@ internal class AndroidHeapDumper(
         return@Runnable
       }
       val toast = Toast(resumedActivity)
-      val iconSize = resumedActivity.resources.getDimensionPixelSize(
+      // Resources from application context: https://github.com/square/leakcanary/issues/2023
+      val iconSize = context.resources.getDimensionPixelSize(
         R.dimen.leak_canary_toast_icon_size
       )
       toast.setGravity(Gravity.CENTER_VERTICAL, 0, -iconSize)
Repository: android/compose-samples
Issue: [JetSurvey]: RadioButton parent should have selectableGroup modifier

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Is there a StackOverflow question about this issue?

- [X] I have searched StackOverflow

### Is this an issue related to one of the samples?

- [X] Yes, this is a specific issue related to this samples repo.

### Sample app

Jetsurvey

### What happened?

RadioButton parent should have selectableGroup modifier set to help TalkBack. Children with selectable modifier should have role set to RadioButton.

### Relevant logcat output

_No response_

### Code of Conduct

- [X] I agree to follow this project's Code of Conduct

Changed files:
Jetsurvey/app/src/main/java/com/example/compose/jetsurvey/survey/question/ChoiceQuestion.kt

diff --git a/Jetsurvey/app/src/main/java/com/example/compose/jetsurvey/survey/question/ChoiceQuestion.kt b/Jetsurvey/app/src/main/java/com/example/compose/jetsurvey/survey/question/ChoiceQuestion.kt
index df0a19b6..18140fbf 100644
--- a/Jetsurvey/app/src/main/java/com/example/compose/jetsurvey/survey/question/ChoiceQuestion.kt
+++ b/Jetsurvey/app/src/main/java/com/example/compose/jetsurvey/survey/question/ChoiceQuestion.kt
@@ -46,6 +46,7 @@ import androidx.compose.ui.draw.clip
 import androidx.compose.ui.graphics.painter.Painter
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.tooling.preview.PreviewParameter
 import androidx.compose.ui.tooling.preview.PreviewParameterProvider
@@ -132,17 +133,22 @@ private fun Answer(
             }
         ),
         modifier = modifier
+            .clip(MaterialTheme.shapes.small)
+            .then(
+                if (isSingleChoice) {
+                    Modifier.selectable(
+                        selected,
+                        onClick = onOptionSelected,
+                        role = Role.RadioButton
+                    )
+                } else {
+                    Modifier.clickable(onClick = onOptionSelected)
+                }
+            )
     ) {
         Row(
             modifier = Modifier
                 .fillMaxWidth()
-                .then(
-                    if (isSingleChoice) {
-                        Modifier.selectable(selected, onClick = onOptionSelected)
-                    } else {
-                        Modifier.clickable(onClick = onOptionSelected)
-                    }
-                )
                 .padding(16.dp),
             verticalAlignment = Alignment.CenterVertically
         ) {
Repository: android/nowinandroid
Issue: [Bug]: News resource cards change size when switching between ForYou and Saved tabs

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Is there a StackOverflow question about this issue?

- [X] I have searched StackOverflow

### What happened?

The news resource cards change size when switching between the For You and Saved tabs. 

[ezgif.com-rotate.webm](https://github.com/android/nowinandroid/assets/873212/7015fdd8-e16c-4505-ab00-81e1e3a4b99c)


Steps to repro
- Open the app and bookmark the first 3 news resources shown on the ForYou screen
- Tap on "Saved" 

Expected result
- The news resource cards don't change in size

Actual result
- The news resource cards change in size slightly which is visually jarring

### Relevant logcat output

_No response_

### Code of Conduct

- [X] I agree to follow this project's Code of Conduct

Changed files:
feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreen.kt

diff --git a/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreen.kt b/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreen.kt
index e2eb4524..25412e85 100644
--- a/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreen.kt
+++ b/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreen.kt
@@ -181,7 +181,7 @@ private fun BookmarksGrid(
     LazyVerticalGrid(
         columns = Adaptive(300.dp),
         contentPadding = PaddingValues(16.dp),
-        horizontalArrangement = Arrangement.spacedBy(32.dp),
+        horizontalArrangement = Arrangement.spacedBy(16.dp),
         verticalArrangement = Arrangement.spacedBy(24.dp),
         state = scrollableState,
         modifier = modifier
Repository: thundernest/k-9
Issue: Issue with search in General settings after rotating the device

### Checklist

- [X] I have used the search function to see if someone else has already submitted the same bug report.
- [X] I will describe the problem with as much detail as possible.

### App version

6.201

### Where did you get the app from?

F-Droid

### Android version

8.1.0

### Device model

Emulator

### Steps to reproduce

1. Go to General settings
2. Click on the Search icon
3. Type something to show results for you
4. Rotate the device to landscape
5. Click on one of results items


### Expected behavior

It must show that item in the settings as usual.

### Actual behavior

It didn't show that item in the settings. Instead, search results loaded again.

### video

https://user-images.githubusercontent.com/8654398/180634571-0529ff9a-41d5-4305-88b3-0bbc3cb06375.mp4



### Logs

_No response_

Changed files:
app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsActivity.kt

diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsActivity.kt b/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsActivity.kt
index 35c4bfd22..e24941654 100644
--- a/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsActivity.kt
+++ b/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsActivity.kt
@@ -100,6 +100,9 @@ class GeneralSettingsActivity : K9Activity(), OnPreferenceStartScreenCallback, S
                 searchPreferenceMenuItem.expandActionView()
                 searchPreferenceActionView.setQuery(searchQuery, false)
             }
+            // searchEnabled should be set to false because it caused to expand the search view again
+            // when we click on any item after each rotation
+            searchEnabled = false
         }
         return true
     }
Repository: thundernest/k-9
Issue: CC field hid when email address is invalid and we focused on the Subject field.

### Checklist

- [X] I have used the search function to see if someone else has already submitted the same bug report.
- [X] I will describe the problem with as much detail as possible.

### App version

6.201

### Where did you get the app from?

F-Droid

### Android version

8.1.0

### Device model

Emulator

### Steps to reproduce

1. Go to Compose
2. fill the To field with a valid email address
3. fill the Cc field with an invalid email address
4. focus on the Subject field

### Expected behavior

the Cc field should remain visible and show error to the user

### Actual behavior

The Cc and Bcc hid and user should open them again to see the error

### Video

https://user-images.githubusercontent.com/8654398/180643788-6d6ce54a-14c7-4333-943d-994cf42bbc99.mp4



### Logs

_No response_

Changed files:
app/ui/legacy/src/main/java/com/fsck/k9/activity/compose/RecipientPresenter.kt, app/ui/legacy/src/main/java/com/fsck/k9/activity/compose/RecipientMvpView.kt

diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/activity/compose/RecipientMvpView.kt b/app/ui/legacy/src/main/java/com/fsck/k9/activity/compose/RecipientMvpView.kt
index 60f5b84f6..e3d8ca855 100644
--- a/app/ui/legacy/src/main/java/com/fsck/k9/activity/compose/RecipientMvpView.kt
+++ b/app/ui/legacy/src/main/java/com/fsck/k9/activity/compose/RecipientMvpView.kt
@@ -72,6 +72,12 @@ class RecipientMvpView(private val activity: MessageCompose) : View.OnFocusChang
     val bccRecipients: List<Recipient>
         get() = bccView.objects
 
+    val isCcTextEmpty: Boolean
+        get() = ccView.text.isEmpty()
+
+    val isBccTextEmpty: Boolean
+        get() = bccView.text.isEmpty()
+
     fun setPresenter(presenter: RecipientPresenter) {
         this.presenter = presenter
         toView.setTokenListener(object : RecipientSelectView.TokenListener<Recipient> {
diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/activity/compose/RecipientPresenter.kt b/app/ui/legacy/src/main/java/com/fsck/k9/activity/compose/RecipientPresenter.kt
index 9b0e6d2ed..11eec7594 100644
--- a/app/ui/legacy/src/main/java/com/fsck/k9/activity/compose/RecipientPresenter.kt
+++ b/app/ui/legacy/src/main/java/com/fsck/k9/activity/compose/RecipientPresenter.kt
@@ -347,14 +347,14 @@ class RecipientPresenter(
     }
 
     private fun hideEmptyExtendedRecipientFields() {
-        if (recipientMvpView.ccAddresses.isEmpty()) {
+        if (recipientMvpView.ccAddresses.isEmpty() && recipientMvpView.isCcTextEmpty) {
             recipientMvpView.setCcVisibility(false)
             if (lastFocusedType == RecipientType.CC) {
                 lastFocusedType = RecipientType.TO
             }
         }
 
-        if (recipientMvpView.bccAddresses.isEmpty()) {
+        if (recipientMvpView.bccAddresses.isEmpty() && recipientMvpView.isBccTextEmpty) {
             recipientMvpView.setBccVisibility(false)
             if (lastFocusedType == RecipientType.BCC) {
                 lastFocusedType = RecipientType.TO