Fix an issue that the FoldStateListener induces a memory leak

FoldStateListener is non-static inner class and keeps reference to
the outer class which is CameraManager. As CameraManager also keeps
context with mContext, memory leak could exist.

Changing FoldStateListener to static inner class, so that the class
won't keep the reference.

Bug: 242264787
Test: Manual test with memory profiling
Change-Id: I77652bd94b50eabc80041e13274b619c0da36601
This commit is contained in:
Kwangkyu Park
2022-08-12 16:28:31 +09:00
parent 00545d0fd6
commit eb11b2401b

View File

@@ -124,9 +124,6 @@ public final class CameraManager {
private HandlerThread mHandlerThread;
private Handler mHandler;
private FoldStateListener mFoldStateListener;
@GuardedBy("mLock")
private ArrayList<WeakReference<DeviceStateListener>> mDeviceStateListeners = new ArrayList<>();
private boolean mFoldedDeviceState;
/**
* @hide
@@ -135,31 +132,39 @@ public final class CameraManager {
void onDeviceStateChanged(boolean folded);
}
private final class FoldStateListener implements DeviceStateManager.DeviceStateCallback {
private static final class FoldStateListener implements DeviceStateManager.DeviceStateCallback {
private final int[] mFoldedDeviceStates;
private ArrayList<WeakReference<DeviceStateListener>> mDeviceStateListeners =
new ArrayList<>();
private boolean mFoldedDeviceState;
public FoldStateListener(Context context) {
mFoldedDeviceStates = context.getResources().getIntArray(
com.android.internal.R.array.config_foldedDeviceStates);
}
private void handleStateChange(int state) {
private synchronized void handleStateChange(int state) {
boolean folded = ArrayUtils.contains(mFoldedDeviceStates, state);
synchronized (mLock) {
mFoldedDeviceState = folded;
ArrayList<WeakReference<DeviceStateListener>> invalidListeners = new ArrayList<>();
for (WeakReference<DeviceStateListener> listener : mDeviceStateListeners) {
DeviceStateListener callback = listener.get();
if (callback != null) {
callback.onDeviceStateChanged(folded);
} else {
invalidListeners.add(listener);
}
}
if (!invalidListeners.isEmpty()) {
mDeviceStateListeners.removeAll(invalidListeners);
mFoldedDeviceState = folded;
ArrayList<WeakReference<DeviceStateListener>> invalidListeners = new ArrayList<>();
for (WeakReference<DeviceStateListener> listener : mDeviceStateListeners) {
DeviceStateListener callback = listener.get();
if (callback != null) {
callback.onDeviceStateChanged(folded);
} else {
invalidListeners.add(listener);
}
}
if (!invalidListeners.isEmpty()) {
mDeviceStateListeners.removeAll(invalidListeners);
}
}
public synchronized void addDeviceStateListener(DeviceStateListener listener) {
listener.onDeviceStateChanged(mFoldedDeviceState);
mDeviceStateListeners.add(new WeakReference<>(listener));
}
@Override
@@ -183,9 +188,8 @@ public final class CameraManager {
public void registerDeviceStateListener(@NonNull CameraCharacteristics chars) {
synchronized (mLock) {
DeviceStateListener listener = chars.getDeviceStateListener();
listener.onDeviceStateChanged(mFoldedDeviceState);
if (mFoldStateListener != null) {
mDeviceStateListeners.add(new WeakReference<>(listener));
mFoldStateListener.addDeviceStateListener(listener);
}
}
}