Skip to content

Memory leak: KiwixMainActivity retained via TextToSpeech$SystemConnection binder stub #5020

Description

@Shahab-hashemi

Description:

LeakCanary detected a memory leak in the nightly build. KiwixMainActivity is being retained in memory after being destroyed, due to a leak chain originating from Android's TextToSpeech system service connection.

Leak trace:

GC Root: Global variable in native code

android.speech.tts.TextToSpeech$SystemConnection$1 instance
    Leaking: UNKNOWN
    Retaining 1.0 MB in 12000 objects
    Anonymous subclass of android.speech.tts.ITextToSpeechSessionCallback$Stub
    (binder stub — retained until the other side is GCed)
    ↓ TextToSpeech$SystemConnection$1.this$1

android.speech.tts.TextToSpeech$SystemConnection instance
    Leaking: UNKNOWN
    Retaining 1.0 MB in 11999 objects
    ↓ TextToSpeech$SystemConnection.this$0

android.speech.tts.TextToSpeech instance
    Leaking: UNKNOWN
    Retaining 1.0 MB in 11997 objects
    mContext instance of org.kiwix.kiwixmobile.main.KiwixMainActivity with mDestroyed = true
    ↓ TextToSpeech.mContext

org.kiwix.kiwixmobile.main.KiwixMainActivity instance
    Leaking: YES (ObjectWatcher was watching this because
    KiwixMainActivity received Activity#onDestroy() callback
    and Activity#mDestroyed is true)
    Retaining 1.0 MB in 11986 objects
    watchDurationMillis = 5694
    retainedDurationMillis = 693

Likely cause:

TextToSpeech holds a reference to the Context passed into its constructor (TextToSpeech.mContext). If KiwixMainActivity (or its Application/base Context) is passed in and the TextToSpeech instance is not released when the activity is destroyed, the underlying SystemConnection binder stub keeps the whole chain alive, preventing KiwixMainActivity from being garbage collected.

Suggested fix:

  • Call TextToSpeech.shutdown() in the appropriate lifecycle method (e.g. onDestroy()) of KiwixMainActivity or wherever the TextToSpeech instance is owned.
  • Consider initializing TextToSpeech with applicationContext instead of the activity context, to avoid tying its lifecycle to the activity.

Environment:

  • Build: Kiwix nightly
  • Detected by: LeakCanary

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions