From eebd44074afbb129c5007cdaa64a3e1ee12c1ab0 Mon Sep 17 00:00:00 2001 From: Angela Wang Date: Tue, 26 Mar 2024 03:46:56 +0000 Subject: [PATCH] Register callback again after service is connected The exception is thrown when trying to unregister a not-registered callback. This may happen when after rebooting the device, the proxy is not attached to the service while registerCallback() is called in onResume(). The callback will not be correctly registered and hence causing this exception when unregisterCallback() is called in onPause(). Add listener to listen the onServiceConnected() callback and re-register the callback if the service is not connected when user enters to the page. Bug: 330116041 Test: manually test the scenario and confirm no exception thrown Change-Id: I1f99d067e28e285bcbfff1f34bd322cdbac8063a --- ...thDetailsHearingAidsPresetsController.java | 73 ++++++++++++++++--- 1 file changed, 62 insertions(+), 11 deletions(-) diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHearingAidsPresetsController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHearingAidsPresetsController.java index 43721f4cf92..feecd9005c6 100644 --- a/src/com/android/settings/bluetooth/BluetoothDetailsHearingAidsPresetsController.java +++ b/src/com/android/settings/bluetooth/BluetoothDetailsHearingAidsPresetsController.java @@ -41,9 +41,12 @@ import com.android.settings.R; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.HapClientProfile; import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.events.OnPause; import com.android.settingslib.core.lifecycle.events.OnResume; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; import com.android.settingslib.utils.ThreadUtils; import java.util.List; @@ -53,13 +56,16 @@ import java.util.List; */ public class BluetoothDetailsHearingAidsPresetsController extends BluetoothDetailsController implements Preference.OnPreferenceChangeListener, - BluetoothHapClient.Callback, OnResume, OnPause { + BluetoothHapClient.Callback, LocalBluetoothProfileManager.ServiceListener, + OnStart, OnResume, OnPause, OnStop { private static final boolean DEBUG = true; private static final String TAG = "BluetoothDetailsHearingAidsPresetsController"; static final String KEY_HEARING_AIDS_PRESETS = "hearing_aids_presets"; + private final LocalBluetoothProfileManager mProfileManager; private final HapClientProfile mHapClientProfile; + @Nullable private ListPreference mPreference; @@ -69,25 +75,34 @@ public class BluetoothDetailsHearingAidsPresetsController extends @NonNull CachedBluetoothDevice device, @NonNull Lifecycle lifecycle) { super(context, fragment, device, lifecycle); - mHapClientProfile = manager.getProfileManager().getHapClientProfile(); + mProfileManager = manager.getProfileManager(); + mHapClientProfile = mProfileManager.getHapClientProfile(); + } + + @Override + public void onStart() { + if (mHapClientProfile != null && !mHapClientProfile.isProfileReady()) { + mProfileManager.addServiceListener(this); + } } @Override public void onResume() { + registerHapCallback(); super.onResume(); - if (mHapClientProfile != null) { - mHapClientProfile.registerCallback(ThreadUtils.getBackgroundExecutor(), this); - } } @Override public void onPause() { - if (mHapClientProfile != null) { - mHapClientProfile.unregisterCallback(this); - } + unregisterHapCallback(); super.onPause(); } + @Override + public void onStop() { + mProfileManager.removeServiceListener(this); + } + @Override public boolean onPreferenceChange(@NonNull Preference preference, @Nullable Object newValue) { if (TextUtils.equals(preference.getKey(), getPreferenceKey())) { @@ -203,9 +218,8 @@ public class BluetoothDetailsHearingAidsPresetsController extends public void onPresetSelectionFailed(@NonNull BluetoothDevice device, int reason) { if (device.equals(mCachedDevice.getDevice())) { if (DEBUG) { - Log.d(TAG, - "onPresetSelectionFailed, device: " + device.getAddress() - + ", reason: " + reason); + Log.d(TAG, "onPresetSelectionFailed, device: " + device.getAddress() + + ", reason: " + reason); } mContext.getMainExecutor().execute(() -> { refresh(); @@ -305,4 +319,41 @@ public class BluetoothDetailsHearingAidsPresetsController extends Toast.makeText(mContext, R.string.bluetooth_hearing_aids_presets_error, Toast.LENGTH_SHORT).show(); } + + private void registerHapCallback() { + if (mHapClientProfile != null) { + try { + mHapClientProfile.registerCallback(ThreadUtils.getBackgroundExecutor(), this); + } catch (IllegalArgumentException e) { + // The callback was already registered + Log.w(TAG, "Cannot register callback: " + e.getMessage()); + } + + } + } + + private void unregisterHapCallback() { + if (mHapClientProfile != null) { + try { + mHapClientProfile.unregisterCallback(this); + } catch (IllegalArgumentException e) { + // The callback was never registered or was already unregistered + Log.w(TAG, "Cannot unregister callback: " + e.getMessage()); + } + } + } + + @Override + public void onServiceConnected() { + if (mHapClientProfile != null && mHapClientProfile.isProfileReady()) { + mProfileManager.removeServiceListener(this); + registerHapCallback(); + refresh(); + } + } + + @Override + public void onServiceDisconnected() { + // Do nothing + } }