[Audiosharing] Refresh preference when onServiceConnected

Test: atest
Bug: 305620450
Flag: com.android.settingslib.flags.enable_le_audio_sharing
Change-Id: I58334f674398ff6e053c178810e9f9d290c0ad2b
This commit is contained in:
Yiyi Shen
2025-03-18 19:02:19 +08:00
parent b96eb497da
commit 0e786c01f7
2 changed files with 116 additions and 14 deletions

View File

@@ -37,19 +37,22 @@ import com.android.settingslib.bluetooth.BluetoothEventManager;
import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.utils.ThreadUtils; import com.android.settingslib.utils.ThreadUtils;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
public class AudioSharingPreferenceController extends BasePreferenceController public class AudioSharingPreferenceController extends BasePreferenceController
implements DefaultLifecycleObserver, BluetoothCallback { implements DefaultLifecycleObserver, BluetoothCallback,
LocalBluetoothProfileManager.ServiceListener {
private static final String TAG = "AudioSharingPreferenceController"; private static final String TAG = "AudioSharingPreferenceController";
private static final String CONNECTED_DEVICES_PREF_KEY = private static final String CONNECTED_DEVICES_PREF_KEY =
"connected_device_audio_sharing_settings"; "connected_device_audio_sharing_settings";
private static final String CONNECTION_PREFERENCES_PREF_KEY = "audio_sharing_settings"; private static final String CONNECTION_PREFERENCES_PREF_KEY = "audio_sharing_settings";
@Nullable private final LocalBluetoothManager mBtManager; @Nullable private final LocalBluetoothManager mBtManager;
@Nullable private final LocalBluetoothProfileManager mProfileManager;
@Nullable private final BluetoothEventManager mEventManager; @Nullable private final BluetoothEventManager mEventManager;
@Nullable private final LocalBluetoothLeBroadcast mBroadcast; @Nullable private final LocalBluetoothLeBroadcast mBroadcast;
@Nullable private Preference mPreference; @Nullable private Preference mPreference;
@@ -94,11 +97,9 @@ public class AudioSharingPreferenceController extends BasePreferenceController
public AudioSharingPreferenceController(Context context, String preferenceKey) { public AudioSharingPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey); super(context, preferenceKey);
mBtManager = Utils.getLocalBtManager(context); mBtManager = Utils.getLocalBtManager(context);
mProfileManager = mBtManager == null ? null : mBtManager.getProfileManager();
mEventManager = mBtManager == null ? null : mBtManager.getEventManager(); mEventManager = mBtManager == null ? null : mBtManager.getEventManager();
mBroadcast = mBroadcast = mProfileManager == null ? null : mProfileManager.getLeAudioBroadcastProfile();
mBtManager == null
? null
: mBtManager.getProfileManager().getLeAudioBroadcastProfile();
mExecutor = Executors.newSingleThreadExecutor(); mExecutor = Executors.newSingleThreadExecutor();
} }
@@ -114,6 +115,13 @@ public class AudioSharingPreferenceController extends BasePreferenceController
} }
mEventManager.registerCallback(this); mEventManager.registerCallback(this);
mBroadcast.registerServiceCallBack(mExecutor, mBroadcastCallback); mBroadcast.registerServiceCallBack(mExecutor, mBroadcastCallback);
if (!AudioSharingUtils.isAudioSharingProfileReady(mProfileManager)) {
if (mProfileManager != null) {
mProfileManager.addServiceListener(this);
}
Log.d(TAG, "Skip updateVisibility. Profile is not ready.");
return;
}
updateVisibility(); updateVisibility();
} }
@@ -129,6 +137,9 @@ public class AudioSharingPreferenceController extends BasePreferenceController
} }
mEventManager.unregisterCallback(this); mEventManager.unregisterCallback(this);
mBroadcast.unregisterServiceCallBack(mBroadcastCallback); mBroadcast.unregisterServiceCallBack(mBroadcastCallback);
if (mProfileManager != null) {
mProfileManager.removeServiceListener(this);
}
} }
@Override @Override
@@ -141,7 +152,6 @@ public class AudioSharingPreferenceController extends BasePreferenceController
if (mPreference != null && CONNECTED_DEVICES_PREF_KEY.equals(getPreferenceKey())) { if (mPreference != null && CONNECTED_DEVICES_PREF_KEY.equals(getPreferenceKey())) {
mPreference.setVisible(false); mPreference.setVisible(false);
} }
updateVisibility();
} }
@Override @Override
@@ -150,6 +160,20 @@ public class AudioSharingPreferenceController extends BasePreferenceController
: UNSUPPORTED_ON_DEVICE; : UNSUPPORTED_ON_DEVICE;
} }
@Override
public void onServiceConnected() {
if (AudioSharingUtils.isAudioSharingProfileReady(mProfileManager)) {
Log.d(TAG, "onServiceConnected, audio sharing ready");
refreshPreference();
if (mProfileManager != null) {
mProfileManager.removeServiceListener(this);
}
}
}
@Override
public void onServiceDisconnected() {}
@Override @Override
public CharSequence getSummary() { public CharSequence getSummary() {
return switch (getPreferenceKey()) { return switch (getPreferenceKey()) {

View File

@@ -26,6 +26,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
@@ -39,6 +40,8 @@ import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothStatusCodes;
import android.content.Context; import android.content.Context;
import android.os.Looper; import android.os.Looper;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule; import android.platform.test.flag.junit.SetFlagsRule;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
@@ -52,9 +55,12 @@ import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils; import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settings.testutils.shadow.ShadowThreadUtils; import com.android.settings.testutils.shadow.ShadowThreadUtils;
import com.android.settingslib.bluetooth.BluetoothEventManager; import com.android.settingslib.bluetooth.BluetoothEventManager;
import com.android.settingslib.bluetooth.LeAudioProfile;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.bluetooth.VolumeControlProfile;
import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.flags.Flags; import com.android.settingslib.flags.Flags;
@@ -122,8 +128,8 @@ public class AudioSharingPreferenceControllerTest {
} }
@Test @Test
@EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onStart_flagOn_registerCallback() { public void onStart_flagOn_registerCallback() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
setupControllerWithKey(PREF_KEY1); setupControllerWithKey(PREF_KEY1);
mController.onStart(mLifecycleOwner); mController.onStart(mLifecycleOwner);
verify(mBtEventManager).registerCallback(mController); verify(mBtEventManager).registerCallback(mController);
@@ -131,8 +137,8 @@ public class AudioSharingPreferenceControllerTest {
} }
@Test @Test
@DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onStart_flagOff_skipRegisterCallback() { public void onStart_flagOff_skipRegisterCallback() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
setupControllerWithKey(PREF_KEY1); setupControllerWithKey(PREF_KEY1);
mController.onStart(mLifecycleOwner); mController.onStart(mLifecycleOwner);
verify(mBtEventManager, never()).registerCallback(mController); verify(mBtEventManager, never()).registerCallback(mController);
@@ -141,8 +147,8 @@ public class AudioSharingPreferenceControllerTest {
} }
@Test @Test
@EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onStop_flagOn_unregisterCallback() { public void onStop_flagOn_unregisterCallback() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
setupControllerWithKey(PREF_KEY1); setupControllerWithKey(PREF_KEY1);
mController.onStop(mLifecycleOwner); mController.onStop(mLifecycleOwner);
verify(mBtEventManager).unregisterCallback(mController); verify(mBtEventManager).unregisterCallback(mController);
@@ -150,8 +156,8 @@ public class AudioSharingPreferenceControllerTest {
} }
@Test @Test
@DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onStop_flagOff_skipUnregisterCallback() { public void onStop_flagOff_skipUnregisterCallback() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
setupControllerWithKey(PREF_KEY1); setupControllerWithKey(PREF_KEY1);
mController.onStop(mLifecycleOwner); mController.onStop(mLifecycleOwner);
verify(mBtEventManager, never()).unregisterCallback(mController); verify(mBtEventManager, never()).unregisterCallback(mController);
@@ -160,15 +166,15 @@ public class AudioSharingPreferenceControllerTest {
} }
@Test @Test
@EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void getAvailabilityStatus_flagOn() { public void getAvailabilityStatus_flagOn() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
setupControllerWithKey(PREF_KEY1); setupControllerWithKey(PREF_KEY1);
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
} }
@Test @Test
@DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void getAvailabilityStatus_flagOff() { public void getAvailabilityStatus_flagOff() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
setupControllerWithKey(PREF_KEY1); setupControllerWithKey(PREF_KEY1);
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
} }
@@ -203,6 +209,59 @@ public class AudioSharingPreferenceControllerTest {
assertThat(mController.getSummary().toString()).isEmpty(); assertThat(mController.getSummary().toString()).isEmpty();
} }
@Test
@EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onStart_profilesReady_refreshVisibility() {
setupControllerWithKey(PREF_KEY2);
setAudioSharingProfilesReady(true);
when(mBroadcast.isEnabled(any())).thenReturn(true);
mController.displayPreference(mScreen);
shadowOf(Looper.getMainLooper()).idle();
mController.onStart(mLifecycleOwner);
shadowOf(Looper.getMainLooper()).idle();
verify(mPreference, never()).setSummary(any());
assertThat(mPreference.isVisible()).isTrue();
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onStart_profilesNotReady_notRefreshVisibility() {
setupControllerWithKey(PREF_KEY2);
setAudioSharingProfilesReady(false);
mController.displayPreference(mScreen);
mController.onStart(mLifecycleOwner);
shadowOf(Looper.getMainLooper()).idle();
verify(mPreference, never()).setSummary(any());
assertThat(mPreference.isVisible()).isFalse();
verify(mLocalBtProfileManager).addServiceListener(mController);
}
@Test
public void onServiceConnected_profilesReady_refreshSummary() {
setupControllerWithKey(PREF_KEY1);
setAudioSharingProfilesReady(true);
mController.displayPreference(mScreen);
mController.onServiceConnected();
shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.getSummary().toString())
.isEqualTo(mContext.getString(R.string.audio_sharing_summary_off));
assertThat(mPreference.isVisible()).isTrue();
verify(mLocalBtProfileManager).removeServiceListener(mController);
}
@Test
public void onServiceConnected_profilesReady_refreshVisibility() {
setupControllerWithKey(PREF_KEY2);
setAudioSharingProfilesReady(true);
when(mBroadcast.isEnabled(any())).thenReturn(true);
mController.displayPreference(mScreen);
mController.onServiceConnected();
shadowOf(Looper.getMainLooper()).idle();
verify(mPreference, never()).setSummary(any());
assertThat(mPreference.isVisible()).isTrue();
verify(mLocalBtProfileManager).removeServiceListener(mController);
}
@Test @Test
public void onBluetoothStateChanged_refreshSummary() { public void onBluetoothStateChanged_refreshSummary() {
setupControllerWithKey(PREF_KEY1); setupControllerWithKey(PREF_KEY1);
@@ -324,7 +383,7 @@ public class AudioSharingPreferenceControllerTest {
setupControllerWithKey(PREF_KEY2); setupControllerWithKey(PREF_KEY2);
mController.displayPreference(mScreen); mController.displayPreference(mScreen);
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
verify(mPreference, times(3)).setVisible(anyBoolean()); verify(mPreference, times(2)).setVisible(anyBoolean());
mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata); mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
verify(mPreference, never()).setSummary(any()); verify(mPreference, never()).setSummary(any());
@@ -341,7 +400,7 @@ public class AudioSharingPreferenceControllerTest {
mController.mBroadcastCallback.onBroadcastUpdateFailed( mController.mBroadcastCallback.onBroadcastUpdateFailed(
/* reason= */ 1, /* broadcastId= */ 1); /* reason= */ 1, /* broadcastId= */ 1);
verify(mPreference, never()).setSummary(any()); verify(mPreference, never()).setSummary(any());
verify(mPreference, times(3)).setVisible(anyBoolean()); verify(mPreference, times(2)).setVisible(anyBoolean());
} }
private void setupControllerWithKey(String preferenceKey) { private void setupControllerWithKey(String preferenceKey) {
@@ -349,4 +408,23 @@ public class AudioSharingPreferenceControllerTest {
mPreference = spy(new Preference(mContext)); mPreference = spy(new Preference(mContext));
when(mScreen.findPreference(preferenceKey)).thenReturn(mPreference); when(mScreen.findPreference(preferenceKey)).thenReturn(mPreference);
} }
private void setAudioSharingProfilesReady(boolean ready) {
if (ready) {
when(mBroadcast.isProfileReady()).thenReturn(true);
LocalBluetoothLeBroadcastAssistant assistant = mock(
LocalBluetoothLeBroadcastAssistant.class);
LeAudioProfile lea = mock(LeAudioProfile.class);
VolumeControlProfile vc = mock(VolumeControlProfile.class);
when(mLocalBtProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(
assistant);
when(mLocalBtProfileManager.getLeAudioProfile()).thenReturn(lea);
when(mLocalBtProfileManager.getVolumeControlProfile()).thenReturn(vc);
when(assistant.isProfileReady()).thenReturn(true);
when(lea.isProfileReady()).thenReturn(true);
when(vc.isProfileReady()).thenReturn(true);
} else {
when(mBroadcast.isProfileReady()).thenReturn(false);
}
}
} }