Search code examples
androidmemory-leakssamsung-mobilegalaxystylus-pen

Samsung Note 3: Activity Memory Leak after pressing SPen side button


Without implementing any SPen related SDK libraries, a memory leak occurs on an AppCompatActivity extended class. The following sequence of events typically triggers the memory leak:

  1. The user presses the side button, which activates the Air Command tool.
  2. Without clicking on any of the Air Command tool's icons, the side button is clicked again.
  3. The screen is rotated, which in this case causes the Activity to be destroyed and restarted.
  4. Doing a Java Heap Dump through Android Studio reveals a memory leak by the destroyed activity.
  5. The analyzer indicates that the activity mContext variable is referenced by the package class: com.samsung.android.smartclip.SpenGestureManager. This is most likely causing the activity memory leak.

Would there be any way to clear the reference to the mContext variable being held by the SpenGestureManager class? This should hopefully allow the Garbage Collector to clear the destroyed activity.

This issue was detected on the following device/Android version (Samsung Galaxy Note 3 Duos):

  • Model Number: SM-N9002
  • Android Version: 4.4.2 (KitKat)
  • Baseband version: N9002ZNUFNK1
  • Rom version: SVA ROM SM-N9002 v9.0

The same application was tested on a Samsung Galaxy Note 10.1 device, which does not appear to have this memory leak issue.


Solution

  • As you can see from LeakCanary's sources, that's a well-known memory leak.

    SpenGestureManager has a static mContext field that leaks a reference to the activity. Yes, a STATIC mContext field.

    I think that can be resolved using reflection. This is a piece of code that should work:

    
        // Perform an if-check to see whether this is a Samsung device
        Class clazz = Class.forName("com.samsung.android.smartclip.SpenGestureManager");
        Field mContext = clazz.getDeclaredField("mContext");
        mContext.setAccessible(true);
        mContext.set(null, null);