I've found a memory leak in Android 5.x Camera2 API which I also reported. The problem is when you use Android Lollipop device that has Camera2 API implemented in LEGACY
mode. On such devices, calling context.getSystemService(Context.CAMERA_SERVICE)
causes context
to be retained so that it won't be garbage collected.
If this context
is your activity that is started multiple times, you can end up with hanging references to dozens of instances of your activity that are never garbage collected.
The issue appears to happen only on Lollipop devices that have Camera2 API implemented in LEGACY
mode (e.g. HTC One M8, Samsung Galaxy S4), while it does not happen on Samsung Galaxy S6 which implements Camera2 API in FULL
mode.
To demonstrate the issue, I've created a small demo app. The app contains two activities: first that contains a button which calls the second activity. The second activity obtains the CameraManager
and queries the level of Camera2 API support for first back-facing camera and returns the result to first activity. If you run the app on device that implements Camera2 API in LEGACY
mode, after tapping the button 98 times, causing GC and then dumping HPROF you will see exactly 98 live instances of Main2Activity
, like this http://www.pohrani.com/f/1H/gs/4EFlHKoj/sgs4.png
If you do the same on device that implements Camera2 API in FULL
mode, you will see 0 live instances of Main2Activity
, like this http://www.pohrani.com/f/2q/bV/4srUZIJL/sgs6.png
Is there a way to workaround this leak?
One might ask why am I doing this? At our company, we are developing barcode and OCR scanning solutions and also a famous PhotoMath app. So we have a scan activity that controls the camera and scanning process. While starting up, activity checks if device supports Camera2 API in either FULL
or LIMITED
mode and attempts to use it for better performance, whilst if Camera2 API is in LEGACY
mode, then we prefer using camera management using old camera API, as we do on pre-Lollipop devices.
Because of the mentioned memory leak, whenever a client that has integrated our SDK into its app starts the scan activity, performs a scan and obtains the result, one instance of scan activity will be leaked due to the bug. If client scans a lot, this can eat up a more than 20 MB of memory - a serious issue!
So if someone knows how to make a workaround for this issue, I'll be eternally grateful!