From 2f55ae15f14c04b7addb6d45aa70260ab1d14ee5 Mon Sep 17 00:00:00 2001 From: Weng Su Date: Tue, 13 Sep 2022 21:47:50 +0800 Subject: [PATCH] Refine WifiTetherSoftApManager and DataSaverBackend to avoid activity leaks - Declare the service callback as static class and use WeakReference to avoid the callback link being occupied - Use application context instead of fragment context to avoid context being occupied by external modules Bug: 237273138 Test: manual test make RunSettingsRoboTests ROBOTEST_FILTER=TetherSettingsTest make RunSettingsRoboTests ROBOTEST_FILTER=WifiTetherPreferenceControllerTest Change-Id: Icca145b8ef08b9949feafbbd4e761f8d50c99181 --- .../settings/datausage/DataSaverBackend.java | 11 +++-- .../WifiTetherPreferenceController.java | 3 +- .../wifi/tether/WifiTetherSoftApManager.java | 49 ++++++++++++++----- 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/com/android/settings/datausage/DataSaverBackend.java b/src/com/android/settings/datausage/DataSaverBackend.java index e39e41aaab5..e47ecbdc997 100644 --- a/src/com/android/settings/datausage/DataSaverBackend.java +++ b/src/com/android/settings/datausage/DataSaverBackend.java @@ -27,6 +27,8 @@ import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.utils.ThreadUtils; +import org.jetbrains.annotations.NotNull; + import java.util.ArrayList; public class DataSaverBackend { @@ -43,10 +45,11 @@ public class DataSaverBackend { private boolean mDenylistInitialized; // TODO: Staticize into only one. - public DataSaverBackend(Context context) { - mContext = context; - mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); - mPolicyManager = NetworkPolicyManager.from(context); + public DataSaverBackend(@NotNull Context context) { + // TODO(b/246537614):Use fragment context to DataSaverBackend class will caused memory leak + mContext = context.getApplicationContext(); + mMetricsFeatureProvider = FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); + mPolicyManager = NetworkPolicyManager.from(mContext); } public void addListener(Listener listener) { diff --git a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java index 73ff31d4e47..c0ac159aebf 100644 --- a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java +++ b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java @@ -56,8 +56,9 @@ public class WifiTetherPreferenceController extends AbstractPreferenceController WifiTetherSoftApManager mWifiTetherSoftApManager; public WifiTetherPreferenceController(Context context, Lifecycle lifecycle) { + // TODO(b/246537032):Use fragment context to WifiManager service will caused memory leak this(context, lifecycle, - context.getSystemService(WifiManager.class), + context.getApplicationContext().getSystemService(WifiManager.class), context.getSystemService(TetheringManager.class), true /* initSoftApManager */, WifiEnterpriseRestrictionUtils.isWifiTetheringAllowed(context)); diff --git a/src/com/android/settings/wifi/tether/WifiTetherSoftApManager.java b/src/com/android/settings/wifi/tether/WifiTetherSoftApManager.java index 2db037fdd0a..f2bacc8db9e 100644 --- a/src/com/android/settings/wifi/tether/WifiTetherSoftApManager.java +++ b/src/com/android/settings/wifi/tether/WifiTetherSoftApManager.java @@ -5,6 +5,7 @@ import android.net.wifi.WifiManager; import android.os.Handler; import android.os.HandlerExecutor; +import java.lang.ref.WeakReference; import java.util.List; /** @@ -15,23 +16,14 @@ public class WifiTetherSoftApManager { private WifiManager mWifiManager; private WifiTetherSoftApCallback mWifiTetherSoftApCallback; - private WifiManager.SoftApCallback mSoftApCallback = new WifiManager.SoftApCallback() { - @Override - public void onStateChanged(int state, int failureReason) { - mWifiTetherSoftApCallback.onStateChanged(state, failureReason); - } - - @Override - public void onConnectedClientsChanged(List clients) { - mWifiTetherSoftApCallback.onConnectedClientsChanged(clients); - } - }; + private WifiManager.SoftApCallback mSoftApCallback; private Handler mHandler; WifiTetherSoftApManager(WifiManager wifiManager, WifiTetherSoftApCallback wifiTetherSoftApCallback) { mWifiManager = wifiManager; mWifiTetherSoftApCallback = wifiTetherSoftApCallback; + mSoftApCallback = new WifiManagerSoftApCallback(this); mHandler = new Handler(); } @@ -43,6 +35,14 @@ public class WifiTetherSoftApManager { mWifiManager.unregisterSoftApCallback(mSoftApCallback); } + void onStateChanged(int state, int failureReason) { + mWifiTetherSoftApCallback.onStateChanged(state, failureReason); + } + + void onConnectedClientsChanged(List clients) { + mWifiTetherSoftApCallback.onConnectedClientsChanged(clients); + } + public interface WifiTetherSoftApCallback { void onStateChanged(int state, int failureReason); @@ -53,4 +53,31 @@ public class WifiTetherSoftApManager { */ void onConnectedClientsChanged(List clients); } + + // TODO(b/246537032):Need to declare the service callback as static class and use + // WeakReference to avoid the callback link being occupied by WifiManager + private static final class WifiManagerSoftApCallback implements + WifiManager.SoftApCallback { + WeakReference mMyClass; + + WifiManagerSoftApCallback(WifiTetherSoftApManager controller) { + mMyClass = new WeakReference<>(controller); + } + + @Override + public void onStateChanged(int state, int failureReason) { + WifiTetherSoftApManager controller = mMyClass.get(); + if (controller == null) return; + + controller.onStateChanged(state, failureReason); + } + + @Override + public void onConnectedClientsChanged(List clients) { + WifiTetherSoftApManager controller = mMyClass.get(); + if (controller == null) return; + + controller.onConnectedClientsChanged(clients); + } + } }