summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFan Zhang <zhfan@google.com>2017-03-03 17:59:23 -0800
committerFan Zhang <zhfan@google.com>2017-03-03 18:01:19 -0800
commitf5f71a9be218e9a3c992573fb8acd6eae114cc81 (patch)
treecd665b4d9e0d9e0177034469653006c373ec7270
parent50aa0008fc47d6250c6f30bf894f6fc0d472d8a3 (diff)
downloadpackages_apps_Settings-f5f71a9be218e9a3c992573fb8acd6eae114cc81.tar.gz
packages_apps_Settings-f5f71a9be218e9a3c992573fb8acd6eae114cc81.tar.bz2
packages_apps_Settings-f5f71a9be218e9a3c992573fb8acd6eae114cc81.zip
Fix ServiceConnectionLeak in network fragment
Change-Id: I43efe9ae31fc2f58361abdb034b0205a3f3e2b71 Fix: 35957226 Test: make RunSettingsRoboTests
-rw-r--r--src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java7
-rw-r--r--src/com/android/settings/network/NetworkDashboardFragment.java2
-rw-r--r--src/com/android/settings/network/TetherPreferenceController.java23
-rw-r--r--tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java18
4 files changed, 44 insertions, 6 deletions
diff --git a/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java b/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java
index 0a1a6281fe..abe14273bb 100644
--- a/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java
+++ b/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java
@@ -88,4 +88,11 @@ public abstract class ObservablePreferenceFragment extends PreferenceFragment {
super.onPause();
}
+ @CallSuper
+ @Override
+ public void onDestroy() {
+ mLifecycle.onDestroy();
+ super.onDestroy();
+ }
+
}
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index f52230b61d..6add7868e3 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -95,7 +95,7 @@ public class NetworkDashboardFragment extends DashboardFragment implements
final List<PreferenceController> controllers = new ArrayList<>();
controllers.add(airplaneModePreferenceController);
controllers.add(mobileNetworkPreferenceController);
- controllers.add(new TetherPreferenceController(context));
+ controllers.add(new TetherPreferenceController(context, lifecycle));
controllers.add(vpnPreferenceController);
controllers.add(new ProxyPreferenceController(context));
controllers.add(mobilePlanPreferenceController);
diff --git a/src/com/android/settings/network/TetherPreferenceController.java b/src/com/android/settings/network/TetherPreferenceController.java
index 5b8d55eee2..f23118a3fa 100644
--- a/src/com/android/settings/network/TetherPreferenceController.java
+++ b/src/com/android/settings/network/TetherPreferenceController.java
@@ -28,6 +28,9 @@ import android.support.v7.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.TetherSettings;
import com.android.settings.core.PreferenceController;
+import com.android.settings.core.lifecycle.Lifecycle;
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnDestroy;
import java.util.concurrent.atomic.AtomicReference;
@@ -35,7 +38,8 @@ import static android.os.UserManager.DISALLOW_CONFIG_TETHERING;
import static com.android.settingslib.RestrictedLockUtils.checkIfRestrictionEnforced;
import static com.android.settingslib.RestrictedLockUtils.hasBaseUserRestriction;
-public class TetherPreferenceController extends PreferenceController {
+public class TetherPreferenceController extends PreferenceController
+ implements LifecycleObserver, OnDestroy {
private static final String KEY_TETHER_SETTINGS = "tether_settings";
@@ -62,12 +66,12 @@ public class TetherPreferenceController extends PreferenceController {
TetherPreferenceController() {
super(null);
mAdminDisallowedTetherConfig = false;
- mBluetoothPan = null;
+ mBluetoothPan = new AtomicReference<>();
mConnectivityManager = null;
- mBluetoothAdapter = null;
+ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
- public TetherPreferenceController(Context context) {
+ public TetherPreferenceController(Context context, Lifecycle lifecycle) {
super(context);
mBluetoothPan = new AtomicReference<>();
mAdminDisallowedTetherConfig = checkIfRestrictionEnforced(
@@ -75,6 +79,9 @@ public class TetherPreferenceController extends PreferenceController {
mConnectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
if (mBluetoothAdapter != null) {
mBluetoothAdapter.getProfileProxy(context, mBtProfileServiceListener,
BluetoothProfile.PAN);
@@ -113,6 +120,14 @@ public class TetherPreferenceController extends PreferenceController {
return KEY_TETHER_SETTINGS;
}
+ @Override
+ public void onDestroy() {
+ final BluetoothProfile profile = mBluetoothPan.getAndSet(null);
+ if (profile != null && mBluetoothAdapter != null) {
+ mBluetoothAdapter.closeProfileProxy(BluetoothProfile.PAN, profile);
+ }
+ }
+
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
void updateSummary() {
if (mPreference == null) {
diff --git a/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java
index a856e8c9a5..6f751eb87a 100644
--- a/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java
@@ -18,9 +18,10 @@ package com.android.settings.network;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothPan;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.net.ConnectivityManager;
-import android.os.UserManager;
import android.support.v7.preference.Preference;
import com.android.settings.R;
@@ -35,6 +36,9 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -65,6 +69,18 @@ public class TetherPreferenceControllerTest {
}
@Test
+ public void goThroughLifecycle_shouldDestoryBluetoothProfile() {
+ final BluetoothPan pan = mock(BluetoothPan.class);
+ final AtomicReference<BluetoothPan> panRef =
+ ReflectionHelpers.getField(mController, "mBluetoothPan");
+ panRef.set(pan);
+
+ mController.onDestroy();
+
+ verify(mBluetoothAdapter).closeProfileProxy(BluetoothProfile.PAN, pan);
+ }
+
+ @Test
public void updateSummary_noPreference_noInteractionWithConnectivityManager() {
mController.updateSummary();
verifyNoMoreInteractions(mConnectivityManager);