How to avoid memory leak in context.getSystemService (Context.CAMERA_SERVICE)?

I detected a memory leak in the Android 5.x Camera2 API, which I also reported . The problem is that you are using an Android Lollipop device that has the Camera2 API implemented in LEGACY mode. On such devices, calling context.getSystemService(Context.CAMERA_SERVICE) causes the context to be saved so that it does not intend to collect garbage.

If this context is your activity that runs several times, you can end up with links to dozens of instances of your activity that never get garbage collected.

The problem seems to only happen on Lollipop devices that have Camera2 APIs implemented in LEGACY mode (e.g. HTC One M8, Samsung Galaxy S4), while this does not happen on Samsung Galaxy S6, which implements Camera2 API in FULL mode .

To demonstrate this problem, I created a small demo application . The application contains two actions: first it contains a button that invokes the second action. The second action receives CameraManager and requests the Camera2 API support level for the first reverse camera and returns the result for the first activity. If you run an application on a device that implements the Camera2 API in LEGACY mode, after pressing the button 98 times, calling GC, and then unloading HPROF, you will see exactly 98 live instances of Main2Activity , for example http://www.pohrani.com/f/ 1H / gs / 4EFlHKoj / sgs4.png

If you do the same on a device that implements the Camera2 API in FULL mode, you will see 0 live instances of Main2Activity , for example, <a3>

Is there any way around this leak?

One may ask, why am I doing this? In our company, we are developing barcode and OCR scanning solutions , as well as the well-known PhotoMath Application . Thus, we have a scanning activity that controls the process of the camera and scanning. At startup, the activity checks whether the device supports Camera2 API in FULL or LIMITED mode, and tries to use it to improve performance, whereas if the Camera2 API is in LEGACY mode, we prefer to use camera control using the old camera API, as we do on devices prior to Lollipop.

Due to the mentioned memory leak, whenever a client who has integrated our SDK in its application starts a scan operation, performs a scan and receives a result, one instance of the scan activity will leak due to an error. If the client scans a lot, it can eat more than 20 MB of memory - a serious problem!

So, if someone knows how to make a workaround for this problem, I will be infinitely grateful!

+5
source share
2 answers

Is there any way around this leak?

You can call getSystemService() on the singleton Application . So, instead of:

 getSystemService(CAMERA_SERVICE) 

would you use:

 getApplicationContext().getSystemService(CAMERA_SERVICE) 

If your assessment is correct, then this will cause these sitelinks to be associated with the existing Application syntax, which is always in your process. This is effectively a β€œpre-leak”, and you cannot leak it further with more links to it.

+5
source

This is an Android bug that has been fixed in L MR1.

Basically, CameraManager saved a link to the context with which it was created, and then connected to the camera service. This connection kept the instance of the camera manager indefinitely and therefore also kept the Context indefinite.

This has been fixed in L MR1 to correctly resolve CameraManager objects if they are no longer referenced.

+1
source

All Articles