network: fix binder object leakage in settings

Summary:
When BT ON and enter into NetworkDashboardFragment, and turning BT OFF and exiting the fragment, the `BluetoothAdapter.closeProfileProxy(BluetoothProfile.PAN)` will not be called.
This causes binder leakage on next time the NetworkDashboardFragment is entered, until killing Settings process.

Reproduce Steps:
1. Turn BT ON
2. Open Settings process
3. Enter "Network & internet" (NetworkDashboardFragment)
4. Turn BT OFF
5. Back to previous page (do not kill Settings process)
* Repeat Step 3-5

Solution:
Do not set value of `mBluetoothPan` to null when `onServiceDisconnected` raised, to ensure the binder object (profile proxy) be closed in lifecycle `onDestroy()`.

Bug: 243128377
Test: enter "Network & internet" page, turn off BT and leave the page
Change-Id: Ieca3e5401c23d1b0ffece1bbb0db96988044262d
This commit is contained in:
Jason Huang
2022-06-27 20:57:22 +08:00
parent 2af8366306
commit 2bb35ff3fc
3 changed files with 128 additions and 13 deletions

View File

@@ -43,6 +43,7 @@ import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.SearchIndexableResource;
import android.text.TextUtils;
import android.util.FeatureFlagUtils;
import android.util.Log;
@@ -97,6 +98,7 @@ public class TetherSettings extends RestrictedSettingsFragment
private SwitchPreference mEthernetTether;
private BroadcastReceiver mTetherChangeReceiver;
private BroadcastReceiver mBluetoothStateReceiver;
private String[] mBluetoothRegexs;
private AtomicReference<BluetoothPan> mBluetoothPan = new AtomicReference<>();
@@ -167,6 +169,12 @@ public class TetherSettings extends RestrictedSettingsFragment
adapter.getProfileProxy(activity.getApplicationContext(), mProfileServiceListener,
BluetoothProfile.PAN);
}
if (mBluetoothStateReceiver == null) {
mBluetoothStateReceiver = new BluetoothStateReceiver();
mContext.registerReceiver(
mBluetoothStateReceiver,
new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
}
setupTetherPreference();
setTopIntroPreferenceTitle();
@@ -216,6 +224,10 @@ public class TetherSettings extends RestrictedSettingsFragment
if (profile != null && adapter != null) {
adapter.closeProfileProxy(BluetoothProfile.PAN, profile);
}
if (mBluetoothStateReceiver != null) {
mContext.unregisterReceiver(mBluetoothStateReceiver);
mBluetoothStateReceiver = null;
}
super.onDestroy();
}
@@ -255,6 +267,30 @@ public class TetherSettings extends RestrictedSettingsFragment
}
}
private class BluetoothStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
Log.i(TAG, "onReceive: action: " + action);
if (TextUtils.equals(action, BluetoothAdapter.ACTION_STATE_CHANGED)) {
final int state =
intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
Log.i(TAG, "onReceive: state: " + BluetoothAdapter.nameForState(state));
final BluetoothProfile profile = mBluetoothPan.get();
switch(state) {
case BluetoothAdapter.STATE_ON:
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (profile == null && adapter != null) {
adapter.getProfileProxy(mContext, mProfileServiceListener,
BluetoothProfile.PAN);
}
break;
}
}
}
}
private class TetherChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context content, Intent intent) {
@@ -558,13 +594,16 @@ public class TetherSettings extends RestrictedSettingsFragment
private BluetoothProfile.ServiceListener mProfileServiceListener =
new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
mBluetoothPan.set((BluetoothPan) proxy);
}
public void onServiceDisconnected(int profile) {
mBluetoothPan.set(null);
}
};
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (mBluetoothPan.get() == null) {
mBluetoothPan.set((BluetoothPan) proxy);
}
}
@Override
public void onServiceDisconnected(int profile) { /* Do nothing */ }
};
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {