leakcanary icon indicating copy to clipboard operation
leakcanary copied to clipboard

Extend InputMethodManager workaround to API level 35

Open jjliu15 opened this issue 1 year ago • 4 comments

Example leak trace:

leakcanary.NoLeakAssertionFailedError: Application memory leaks were detected:
====================================
HEAP ANALYSIS RESULT
====================================
1 APPLICATION LEAKS

References underlined with "~~~" are likely causes.
Learn more at [https://squ.re/leaks](https://www.google.com/url?q=https://squ.re/leaks&sa=D).

44061 bytes retained by leaking objects
Signature: 4f5d3e652eeacb84138b7a40e62b473fe98037ce
┬───
│ GC Root: System class
│
├─ android.view.inputmethod.InputMethodManager class
│    Leaking: NO (InputMethodManager↓ is not leaking and a class is never leaking)
│    ↓ static InputMethodManager.sInstance
├─ android.view.inputmethod.InputMethodManager instance
│    Leaking: NO (InputMethodManager is a singleton)
│    ↓ InputMethodManager.mNextServedView
│                         ~~~~~~~~~~~~~~~
├─ com.android.internal.policy.DecorView instance
│    Leaking: YES (View.mContext references a destroyed activity)
│    Retaining 44.1 kB in 683 objects
│    View not part of a window view hierarchy
│    View.mAttachInfo is null (view detached)
│    View.mWindowAttachCount = 1
│    mContext instance of com.android.internal.policy.DecorContext, wrapping activity androidx.test.core.app.InstrumentationActivityInvoker$EmptyActivity with mDestroyed = true
│    ↓ DecorView.mContentRoot
├─ android.widget.LinearLayout instance
│    Leaking: YES (DecorView↑ is leaking and View.mContext references a destroyed activity)
│    Retaining 2.3 kB in 23 objects
│    View is part of a window view hierarchy
│    View.mAttachInfo is null (view detached)
│    View.mWindowAttachCount = 1
│    mContext instance of androidx.test.core.app.InstrumentationActivityInvoker$EmptyActivity with mDestroyed = true
│    ↓ View.mContext
╰→ androidx.test.core.app.InstrumentationActivityInvoker$EmptyActivity instance
​     Leaking: YES (ObjectWatcher was watching this because androidx.test.core.app.InstrumentationActivityInvoker$EmptyActivity received Activity#onDestroy() callback and Activity#mDestroyed is true)
​     Retaining 3.0 kB in 40 objects
​     key = 2259ec5d-3313-40b0-bf3a-9b10cff01525
​     watchDurationMillis = 10407
​     retainedDurationMillis = 5406
​     mApplication instance of com.google.android.libraries.ads.mobile.maitier.testapps.genericapp.MainApplication
​     mBase instance of android.app.ContextImpl
====================================
0 LIBRARY LEAKS

A Library Leak is a leak caused by a known bug in 3rd party code that you do not have control over.
See [https://square.github.io/leakcanary/fundamentals-how-leakcanary-works/#4-categorizing-leaks](https://www.google.com/url?q=https://square.github.io/leakcanary/fundamentals-how-leakcanary-works/%234-categorizing-leaks&sa=D)
====================================
0 UNREACHABLE OBJECTS

An unreachable object is still in memory but LeakCanary could not find a strong reference path
from GC roots.
====================================
METADATA

Please include this in bug reports and Stack Overflow questions.

Build.VERSION.SDK_INT: 35
Build.MANUFACTURER: Google
LeakCanary version: v2.14
Class count: 36865
Instance count: 240339
Primitive array count: 177999
Object array count: 32355
Thread count: 62
Heap total bytes: 33628842
Bitmap count: 1
Bitmap total bytes: 1025
Large bitmap count: 0
Large bitmap total bytes: 0
Db 1: open /data/user/0/com.google.android.libraries.ads.mobile.maitier.testapps.genericapp/no_backup/androidx.work.workdb
Stats: LruCache[maxSize=3000,hits=128865,misses=223741,hitRate=36%] RandomAccess[bytes=11069875,reads=223741,travel=89466659815,range=40517377,size=50657186]
assertionTag: leakcanary
waitForRetainedDurationMillis: 5129
totalDurationMillis: 35168
Analysis duration: 21514 ms
Heap dump file path: /data/user/0/com.google.android.libraries.ads.mobile.maitier.testapps.genericapp/files/instrumentation_tests_2025-01-14_14-58-38_041.hprof
Heap dump timestamp: 1736895548072
Heap dump duration: 2510 ms
====================================
	at leakcanary.NoLeakAssertionFailedError$Companion.throwOnApplicationLeaks$lambda$3(NoLeakAssertionFailedError.kt:25)
	at leakcanary.NoLeakAssertionFailedError$Companion.$r8$lambda$YWXscVJi44IEBq_-uq5c_WHdK1k(Unknown Source:0)
	at leakcanary.NoLeakAssertionFailedError$Companion$$ExternalSyntheticLambda0.reportHeapAnalysis(Unknown Source:0)
	at leakcanary.AndroidDetectLeaksAssert.runLeakChecks(AndroidDetectLeaksAssert.kt:95)
	at leakcanary.AndroidDetectLeaksAssert.assertNoLeaks(AndroidDetectLeaksAssert.kt:34)
	at leakcanary.LeakAssertions.assertNoLeaks(LeakAssertions.kt:21)
	at com.google.android.libraries.ads.mobile.maitier.MaitierLeakRule$apply$1.evaluate([MaitierLeakRule.kt:46](https://cs.corp.google.com/#search/&q=f:com/google/android/libraries/ads/mobile/maitier/MaitierLeakRule.kt:46&ws=jamesjliu/18240&snapshot=114))
	at org.junit.rules.TestWatcher$1.evaluate([TestWatcher.java:61](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/rules/TestWatcher.java?q=evaluate&l=61&ws=jamesjliu/18240&snapshot=114))
	at org.junit.rules.ExternalResource$1.evaluate([ExternalResource.java:54](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/rules/ExternalResource.java?q=evaluate&l=54&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.ParentRunner$3.evaluate([ParentRunner.java:308](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/ParentRunner.java?q=evaluate&l=308&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate([BlockJUnit4ClassRunner.java:100](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/BlockJUnit4ClassRunner.java?q=evaluate&l=100&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.ParentRunner.runLeaf([ParentRunner.java:368](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/ParentRunner.java?q=evaluate&l=368&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.BlockJUnit4ClassRunner.runChild([BlockJUnit4ClassRunner.java:103](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/BlockJUnit4ClassRunner.java?q=runLeaf&l=103&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.BlockJUnit4ClassRunner.runChild([BlockJUnit4ClassRunner.java:63](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/BlockJUnit4ClassRunner.java?q=runChild&l=63&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.ParentRunner$4.run([ParentRunner.java:333](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/ParentRunner.java?q=runChild&l=333&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.ParentRunner$1.schedule([ParentRunner.java:81](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/ParentRunner.java?q=run&l=81&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.ParentRunner.runChildren([ParentRunner.java:331](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/ParentRunner.java?q=schedule&l=331&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.ParentRunner.-$$Nest$mrunChildren(Unknown Source:0)
	at org.junit.runners.ParentRunner$2.evaluate([ParentRunner.java:295](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/ParentRunner.java?q=runChildren&l=295&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.ParentRunner$3.evaluate([ParentRunner.java:308](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/ParentRunner.java?q=evaluate&l=308&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.ParentRunner.run([ParentRunner.java:420](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/ParentRunner.java?q=evaluate&l=420&ws=jamesjliu/18240&snapshot=114))
	at androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:162)
	at org.junit.runners.Suite.runChild([Suite.java:128](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/Suite.java?l=128&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.Suite.runChild([Suite.java:27](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/Suite.java?q=runChild&l=27&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.ParentRunner$4.run([ParentRunner.java:333](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/ParentRunner.java?q=runChild&l=333&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.ParentRunner$1.schedule([ParentRunner.java:81](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/ParentRunner.java?q=run&l=81&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.ParentRunner.runChildren([ParentRunner.java:331](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/ParentRunner.java?q=schedule&l=331&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.ParentRunner.-$$Nest$mrunChildren(Unknown Source:0)
	at org.junit.runners.ParentRunner$2.evaluate([ParentRunner.java:295](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/ParentRunner.java?q=runChildren&l=295&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.ParentRunner$3.evaluate([ParentRunner.java:308](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/ParentRunner.java?q=evaluate&l=308&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runners.ParentRunner.run([ParentRunner.java:420](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runners/ParentRunner.java?q=evaluate&l=420&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runner.JUnitCore.run([JUnitCore.java:141](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runner/JUnitCore.java?q=run&l=141&ws=jamesjliu/18240&snapshot=114))
	at org.junit.runner.JUnitCore.run([JUnitCore.java:119](https://cs.corp.google.com/piper///depot/google3/third_party/java_src/junit/main/java/org/junit/runner/JUnitCore.java?q=run&l=119&ws=jamesjliu/18240&snapshot=114))
	at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:68)
	at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:59)
	at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:467)
	at android.app.Instrumentation$InstrumentationThread.run([Instrumentation.java:2594](https://cs.corp.google.com/#search/&q=f:android/app/Instrumentation.java))

jjliu15 avatar Jan 15 '25 00:01 jjliu15

CLA assistant check
All committers have signed the CLA.

CLAassistant avatar Jan 15 '25 00:01 CLAassistant

@jjliu15 can you share a sample leaktrace on api 35?

pyricau avatar Jan 15 '25 06:01 pyricau

@pyricau added to the description. I verified locally that this PR fixes the leak

jjliu15 avatar Jan 15 '25 17:01 jjliu15

Hi @pyricau, could you take another look? Thanks!

jjliu15 avatar Jan 27 '25 18:01 jjliu15