Search code examples
leakcanary

Could this leak be caused by the Android 11 DP2


I'm using the Android 11 DP2 on a Pixel 4 XL, and since then, I get this leak a lot. I suspect that it's caused by the developer preview, but I'm not entirely sure.

I tried to search for this leak online, but I didn't find anything related.

What do you think?

┬───
│ GC Root: System class
│
├─ android.app.ApplicationPackageManager class
│    Leaking: NO (a class is never leaking)
│    ↓ static ApplicationPackageManager.mHasSystemFeatureCache
│                                       ~~~~~~~~~~~~~~~~~~~~~~
├─ android.app.ApplicationPackageManager$1 instance
│    Leaking: UNKNOWN
│    Anonymous subclass of android.app.PropertyInvalidatedCache
│    ↓ ApplicationPackageManager$1.mCache
│                                  ~~~~~~
├─ android.app.PropertyInvalidatedCache$1 instance
│    Leaking: UNKNOWN
│    Anonymous subclass of java.util.LinkedHashMap
│    ↓ PropertyInvalidatedCache$1.tail
│                                 ~~~~
├─ java.util.LinkedHashMap$LinkedHashMapEntry instance
│    Leaking: UNKNOWN
│    ↓ LinkedHashMap$LinkedHashMapEntry.key
│                                       ~~~
├─ android.app.ApplicationPackageManager$HasSystemFeatureQuery instance
│    Leaking: UNKNOWN
│    ↓ ApplicationPackageManager$HasSystemFeatureQuery.this$0
│                                                      ~~~~~~
├─ android.app.ApplicationPackageManager instance
│    Leaking: UNKNOWN
│    ↓ ApplicationPackageManager.mContext
│                                ~~~~~~~~
├─ android.app.ContextImpl instance
│    Leaking: UNKNOWN
│    ↓ ContextImpl.mAutofillClient
│                  ~~~~~~~~~~~~~~~
╰→ com.example.app.ui.activities.SplashActivity instance
​     Leaking: YES (ObjectWatcher was watching this because com.example.app.ui.activities.SplashActivity received Activity#onDestroy() callback and Activity#mDestroyed is true)
​     key = 6a69a2a3-1d38-4d27-8c4c-cae915bea1b1
​     watchDurationMillis = 15093
​     retainedDurationMillis = 10089

METADATA

Build.VERSION.SDK_INT: 29
Build.MANUFACTURER: Google
LeakCanary version: 2.2
App process name: com.example.app
Analysis duration: 4326 ms```

Solution

  • Yes, this is very likely to be an Android leak. No idea if it's new, but I haven't seen it before. Do you do anything special with auto fill?

    You should report it on the Android bug tracker, ideally with a sample project to reproduce it. If you can't reproduce easily, at least providing a link to a heap dump would help investigating.

    Based on the names involved in the leaktrace, if ApplicationPackageManager has an application scope (and therefore is not leaking) then ContextImpl.mAutofillClient is holding on to an activity reference for too long.

    The field is defined here: https://android.googlesource.com/platform/frameworks/base/+blame/master/core/java/android/app/ContextImpl.java#235

    I haven't found any recent changes in autofill that would explain this leak. We can see in the source code of Activity that when an activity gets its base context attached, it sets itself as the autofill client for that base context: https://android.googlesource.com/platform/frameworks/base/+blame/master/core/java/android/app/Activity.java#1124

    It never unsets itself, so either that's the mistake, or the base context is expected to have the same scope as the activity.

    Another thing that I find weird though is static ApplicationPackageManager.mHasSystemFeatureCache which means that ApplicationPackageManager has a static fields that starts with m (member field). That's a weird name, usually a mistake that doesn't happen in the android sources. And indeed I can't find it: https://android.googlesource.com/platform/frameworks/base/+blame/master/core/java/android/app/ApplicationPackageManager.java but maybe they haven't shared the updated sources yet? What device are you using this on?