From 1e3d595b2257296195a7ee54f1459f9dd0759cc4 Mon Sep 17 00:00:00 2001 From: Hugh Chen Date: Fri, 1 Jul 2022 08:17:39 +0000 Subject: [PATCH] Fix memory leak in TetherSettings - Make declare callback as static class to avoid memory leak. Bug: 236914626 Test: manual test Change-Id: Icdf511dc14d62e6422bbe4e30d4345f6944d81a8 --- src/com/android/settings/TetherSettings.java | 57 +++++++++++++++----- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java index 012996b878d..561fde8178a 100644 --- a/src/com/android/settings/TetherSettings.java +++ b/src/com/android/settings/TetherSettings.java @@ -324,13 +324,13 @@ public class TetherSettings extends RestrictedSettingsFragment mStartTetheringCallback = new OnStartTetheringCallback(this); - mTetheringEventCallback = new TetheringEventCallback(); + mTetheringEventCallback = new TetheringEventCallback(this); mTm.registerTetheringEventCallback(r -> mHandler.post(r), mTetheringEventCallback); mMassStorageActive = Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState()); registerReceiver(); - mEthernetListener = new EthernetListener(); + mEthernetListener = new EthernetListener(this); if (mEm != null) mEm.addInterfaceStateListener(r -> mHandler.post(r), mEthernetListener); @@ -640,25 +640,56 @@ public class TetherSettings extends RestrictedSettingsFragment } } - private final class TetheringEventCallback implements TetheringManager.TetheringEventCallback { + private static final class TetheringEventCallback implements + TetheringManager.TetheringEventCallback { + final WeakReference mTetherSettings; + + TetheringEventCallback(TetherSettings settings) { + mTetherSettings = new WeakReference<>(settings); + } + @Override public void onTetheredInterfacesChanged(List interfaces) { - Log.d(TAG, "onTetheredInterfacesChanged() interfaces : " + interfaces.toString()); - String[] tethered = interfaces.toArray(new String[interfaces.size()]); - updateUsbState(tethered); - updateBluetoothAndEthernetState(tethered); + final TetherSettings tetherSettings = mTetherSettings.get(); + if (tetherSettings == null) { + return; + } + tetherSettings.onTetheredInterfacesChanged(interfaces); } } - private final class EthernetListener implements EthernetManager.InterfaceStateListener { + void onTetheredInterfacesChanged(List interfaces) { + Log.d(TAG, "onTetheredInterfacesChanged() interfaces : " + interfaces.toString()); + final String[] tethered = interfaces.toArray(new String[interfaces.size()]); + updateUsbState(tethered); + updateBluetoothAndEthernetState(tethered); + } + + private static final class EthernetListener implements EthernetManager.InterfaceStateListener { + final WeakReference mTetherSettings; + + EthernetListener(TetherSettings settings) { + mTetherSettings = new WeakReference<>(settings); + } + + @Override public void onInterfaceStateChanged(@NonNull String iface, int state, int role, @NonNull IpConfiguration configuration) { - if (state == EthernetManager.STATE_LINK_UP) { - mAvailableInterfaces.add(iface); - } else { - mAvailableInterfaces.remove(iface); + final TetherSettings tetherSettings = mTetherSettings.get(); + if (tetherSettings == null) { + return; } - updateBluetoothAndEthernetState(); + tetherSettings.onInterfaceStateChanged(iface, state, role, configuration); } } + + void onInterfaceStateChanged(@NonNull String iface, int state, int role, + @NonNull IpConfiguration configuration) { + if (state == EthernetManager.STATE_LINK_UP) { + mAvailableInterfaces.add(iface); + } else { + mAvailableInterfaces.remove(iface); + } + updateBluetoothAndEthernetState(); + } }