Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a07650b authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Workaround an interpreter behavior to fix leak

When a local variable (cachedThumbnailData) gets out of scope,
the interpreter might still keep a reference to it in the
register. Thus, we extract the handling of this local variable
into a method such that it gets removed from the register.

Test: Open recents, go home, take dump, make sure no reference
from HandlerThread to ThumbnailData is still existing.
Fixes: 37630958

Change-Id: If25456b212341be7a66882a0adfd5afb4a64ce23
parent 04225787
Loading
Loading
Loading
Loading
+52 −44
Original line number Diff line number Diff line
@@ -161,6 +161,31 @@ class BackgroundTaskLoader implements Runnable {
                // If we've stopped the loader, then fall through to the above logic to wait on
                // the load thread
                if (ssp != null) {
                    processLoadQueueItem(ssp);
                }

                // If there are no other items in the list, then just wait until something is added
                if (!mCancelled && mLoadQueue.isEmpty()) {
                    synchronized(mLoadQueue) {
                        try {
                            mWaitingOnLoadQueue = true;
                            mLoadQueue.wait();
                            mWaitingOnLoadQueue = false;
                        } catch (InterruptedException ie) {
                            ie.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    /**
     * This needs to be in a separate method to work around an surprising interpreter behavior:
     * The register will keep the local reference to cachedThumbnailData even if it falls out of
     * scope. Putting it into a method fixes this issue.
     */
    private void processLoadQueueItem(SystemServicesProxy ssp) {
        // Load the next item from the queue
        final Task t = mLoadQueue.nextTask();
        if (t != null) {
@@ -190,7 +215,7 @@ class BackgroundTaskLoader implements Runnable {
            }

            if (DEBUG) Log.d(TAG, "Loading thumbnail: " + t.key);
                        ThumbnailData cachedThumbnailData = ssp.getTaskThumbnail(t.key.id,
            final ThumbnailData cachedThumbnailData = ssp.getTaskThumbnail(t.key.id,
                    true /* reducedResolution */);

            if (cachedThumbnailData.thumbnail == null) {
@@ -199,26 +224,9 @@ class BackgroundTaskLoader implements Runnable {

            if (!mCancelled) {
                // Notify that the task data has changed
                            final Drawable newIcon = cachedIcon;
                            final ThumbnailData newThumbnailData = cachedThumbnailData;
                final Drawable finalIcon = cachedIcon;
                mMainThreadHandler.post(
                                    () -> t.notifyTaskDataLoaded(newThumbnailData, newIcon));
                        }
                    }
                }

                // If there are no other items in the list, then just wait until something is added
                if (!mCancelled && mLoadQueue.isEmpty()) {
                    synchronized(mLoadQueue) {
                        try {
                            mWaitingOnLoadQueue = true;
                            mLoadQueue.wait();
                            mWaitingOnLoadQueue = false;
                        } catch (InterruptedException ie) {
                            ie.printStackTrace();
                        }
                    }
                }
                        () -> t.notifyTaskDataLoaded(cachedThumbnailData, finalIcon));
            }
        }
    }