Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Context Memory Leak ListView due to AudioManager

Tags:

I have a ListView and I would expect it to be cleared from memory when the activity finishes. However, it appears that it is leaking. When I check the Memory Dump, and get the pathToGC for the ListView I get the following,

Class Name                                                          | Shallow Heap | Retained Heap 
android.widget.ExpandableListView @ 0x4063e560                      |          768 |        39,904 
|- list, mList com.hitpost.TeamChooser @ 0x405f92e8                 |          176 |         1,648 
|  '- mOuterContext android.app.ContextImpl @ 0x40657368            |          160 |           304 
|     '- mContext android.media.AudioManager @ 0x40662600           |           40 |           168 
|        '- this$0 android.media.AudioManager$1 @ 0x406626b0 Unknown|           24 |            24 

I see this same context leaking on a lot of of my ListView's. The trick is that, I am not using AudioManager anywhere in my app at all, no sound coming from the app at all. Please help, it's driving me crazy. Obviously trying to figure out why this is happening and what could be the root issue?

like image 243
Leo Avatar asked Jun 22 '11 18:06

Leo


4 Answers

Not related to OP's leak, but for people who come in here because of AudioManager causing leak:

If you see this leak because you are using VideoView, probably is because of this bug: https://code.google.com/p/android/issues/detail?id=152173

VideoView never release AudioManager if video being loaded.

the fix is, as mentioned in the link, create VideoView manually using ApplicationContext.

Edit: this work around will work, until... if the video decoder says the video has an encoding problem. VideoView tries to pop up a AlertDialog using application context. Than a crash happens.

The only work around I can think is to keep creating video view using activity context, and in activity.onDestroy, set AudioManager's mContext to application context using reflection.

Note: have to get the AudioManager using activity.getSystemService(Context.AUDIO_SERVICE) rather than activity.getApplicationContext.getSystemService(Context.AUDIO_SERVICE), since AudioManager is an member variable of Context (you will get wrong instance of AudioManager if you get it from application context).

At last, you may wonder why a member variable (AudioManager) is preventing the class (Activity) to being garbage collected. From the memory analyzer, it shows AudioManager is owned by native stack. So AudioManager somehow did not clean itself properly.

like image 140
Helin Wang Avatar answered Oct 11 '22 20:10

Helin Wang


There are several references to AudioManager in your code that you don't create actively. E.g. each clickable View might have one to play onClick sounds [source]. I guess that is the link.

The code looks like it would not create references to AudioManager if you disable the click sounds in your Settings. You could try that and check if there is still a leak.

The reason for your leak might be that you are holding onto some View object in your ListView (Adapter?) code. If you keep them around then you might have a View that has an AudioManager reference and that keeps a Context reference)

like image 30
zapl Avatar answered Oct 11 '22 20:10

zapl


I had this same issue but it went away after following the below advice.

Mr Guy recommends not doing heap dumps in the debugger and causing a few GCs before getting the dump. https://groups.google.com/forum/?fromgroups=#!topic/android-developers/ew6lfZUH0z8

like image 32
Sean Moore Avatar answered Oct 11 '22 22:10

Sean Moore


You can use application context to avoid leaks in this case. I don't know why but when I started to use application context the problem was gone.

like image 33
Bracadabra Avatar answered Oct 11 '22 22:10

Bracadabra