Use a weak reference to the context in InputManager

It has been reported that a recent change to InputManager is
causing a memory leak. We were already planning to change it in a
way that this issue would no longer happen, but since it's a
refactor that will take some time, this is a temporary solution
that Prabir suggested; if we keep a weak reference to the context,
it will be freed when there is no other active references.

Bug: 267241786
Test: will ask for a test run of this change
Change-Id: I7e894ba1f014bba36f6ea2566b11426d17d84f68
(cherry picked from commit d87354712e)
Merged-In: I7e894ba1f014bba36f6ea2566b11426d17d84f68
This commit is contained in:
Josep del Rio
2023-02-16 22:50:19 +00:00
committed by Cherrypicker Worker
parent 74efadf738
commit 71feb32d93

View File

@@ -74,6 +74,7 @@ import com.android.internal.os.SomeArgs;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -99,13 +100,12 @@ public final class InputManager {
private final IInputManager mIm;
/**
* InputManager has historically used its own static getter {@link #getInstance()} that doesn't
* provide a context. We provide a Context to the InputManager instance through the
* {@link android.app.SystemServiceRegistry}. Methods that need a Context must use
* {@link #getContext()} to obtain it.
* We hold a weak reference to the context to avoid leaking it indefinitely,
* since we currently store the input manager instance as a static variable that
* will outlive any context.
*/
@Nullable
private Context mLateInitContext;
private WeakReference<Context> mWeakContext;
/**
* Whether a PointerIcon is shown for stylus pointers.
@@ -372,8 +372,8 @@ public final class InputManager {
throw new IllegalStateException(e);
}
}
if (sInstance.mLateInitContext == null) {
sInstance.mLateInitContext = context;
if (sInstance.mWeakContext == null || sInstance.mWeakContext.get() == null) {
sInstance.mWeakContext = new WeakReference(context);
}
return sInstance;
}
@@ -381,9 +381,14 @@ public final class InputManager {
@NonNull
private Context getContext() {
return Objects.requireNonNull(mLateInitContext,
WeakReference<Context> weakContext = Objects.requireNonNull(mWeakContext,
"A context is required for InputManager. Get the InputManager instance using "
+ "Context#getSystemService before calling this method.");
// If we get at this point, an app calling this function could potentially expect a
// Context that has disappeared due to garbage collection. Holding a weak reference
// is a temporary solution that should be resolved before the release of a
// production version. This is being tracked in b/267758905
return Objects.requireNonNull(weakContext.get(), "missing Context");
}
/**