Loading src/com/android/settings/connecteddevice/audiosharing/AudioSharingBasePreferenceController.java +1 −1 Original line number Diff line number Diff line Loading @@ -64,7 +64,7 @@ public abstract class AudioSharingBasePreferenceController extends BasePreferenc mPreference.setVisible(isVisible); } private boolean isBroadcasting() { protected boolean isBroadcasting() { return mBroadcast != null && mBroadcast.isEnabled(null); } } src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java +4 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.os.Bundle; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsCategoryController; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.widget.SettingsMainSwitchBar; Loading @@ -34,6 +35,7 @@ public class AudioSharingDashboardFragment extends DashboardFragment private AudioSharingDeviceVolumeGroupController mAudioSharingDeviceVolumeGroupController; private CallsAndAlarmsPreferenceController mCallsAndAlarmsPreferenceController; private AudioSharingNamePreferenceController mAudioSharingNamePreferenceController; private AudioStreamsCategoryController mAudioStreamsCategoryController; public AudioSharingDashboardFragment() { super(); Loading Loading @@ -73,6 +75,7 @@ public class AudioSharingDashboardFragment extends DashboardFragment mCallsAndAlarmsPreferenceController = use(CallsAndAlarmsPreferenceController.class); mCallsAndAlarmsPreferenceController.init(this); mAudioSharingNamePreferenceController = use(AudioSharingNamePreferenceController.class); mAudioStreamsCategoryController = use(AudioStreamsCategoryController.class); } @Override Loading @@ -98,5 +101,6 @@ public class AudioSharingDashboardFragment extends DashboardFragment mAudioSharingDeviceVolumeGroupController.updateVisibility(isVisible); mCallsAndAlarmsPreferenceController.updateVisibility(isVisible); mAudioSharingNamePreferenceController.updateVisibility(isVisible); mAudioStreamsCategoryController.updateVisibility(isVisible); } } src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java +26 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; public class AudioSharingUtils { Loading Loading @@ -230,6 +231,31 @@ public class AudioSharingUtils { return false; } /** * Retrieves the one and only active Bluetooth LE Audio sink device, regardless if the device is * currently in an audio sharing session. * * @param manager The LocalBluetoothManager instance used to fetch connected devices. * @return An Optional containing the active LE Audio device, or an empty Optional if not found. */ public static Optional<CachedBluetoothDevice> getActiveSinkOnAssistant( LocalBluetoothManager manager) { if (manager == null) { Log.w(TAG, "getActiveSinksOnAssistant(): LocalBluetoothManager is null!"); return Optional.empty(); } var groupedDevices = AudioSharingUtils.fetchConnectedDevicesByGroupId(manager); var leadDevices = AudioSharingUtils.buildOrderedConnectedLeadDevices(manager, groupedDevices, false); if (!leadDevices.isEmpty() && AudioSharingUtils.isActiveLeAudioDevice(leadDevices.get(0))) { return Optional.of(leadDevices.get(0)); } else { Log.w(TAG, "getActiveSinksOnAssistant(): No active lead device!"); } return Optional.empty(); } /** Toast message on main thread. */ public static void toastMessage(Context context, String message) { ThreadUtils.postOnMainThread( Loading src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsActiveDeviceSummaryUpdater.java +1 −21 Original line number Diff line number Diff line Loading @@ -30,8 +30,6 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.utils.ThreadUtils; import java.util.Optional; public class AudioStreamsActiveDeviceSummaryUpdater implements BluetoothCallback { private static final String TAG = "AudioStreamsActiveDeviceSummaryUpdater"; private static final boolean DEBUG = BluetoothUtils.D; Loading Loading @@ -82,31 +80,13 @@ public class AudioStreamsActiveDeviceSummaryUpdater implements BluetoothCallback } private String getSummary() { var activeSink = getActiveSinkOnAssistant(mBluetoothManager); var activeSink = AudioSharingUtils.getActiveSinkOnAssistant(mBluetoothManager); if (activeSink.isEmpty()) { return "No active LE Audio device"; } return activeSink.get().getName(); } private static Optional<CachedBluetoothDevice> getActiveSinkOnAssistant( LocalBluetoothManager manager) { if (manager == null) { Log.w(TAG, "getActiveSinksOnAssistant(): LocalBluetoothManager is null!"); return Optional.empty(); } var groupedDevices = AudioSharingUtils.fetchConnectedDevicesByGroupId(manager); var leadDevices = AudioSharingUtils.buildOrderedConnectedLeadDevices(manager, groupedDevices, false); if (!leadDevices.isEmpty() && AudioSharingUtils.isActiveLeAudioDevice(leadDevices.get(0))) { return Optional.of(leadDevices.get(0)); } else { Log.w(TAG, "getActiveSinksOnAssistant(): No active lead device!"); } return Optional.empty(); } /** Interface definition for a callback to be invoked when the summary has been changed. */ interface OnSummaryChangeListener { /** Loading src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsCategoryController.java +70 −2 Original line number Diff line number Diff line Loading @@ -16,15 +16,64 @@ package com.android.settings.connecteddevice.audiosharing.audiostreams; import android.annotation.Nullable; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.util.Log; import androidx.annotation.NonNull; import androidx.lifecycle.DefaultLifecycleObserver; import androidx.lifecycle.LifecycleOwner; import com.android.settings.bluetooth.Utils; import com.android.settings.connecteddevice.audiosharing.AudioSharingBasePreferenceController; import com.android.settings.connecteddevice.audiosharing.AudioSharingUtils; import com.android.settings.flags.Flags; import com.android.settings.widget.PreferenceCategoryController; import com.android.settingslib.bluetooth.BluetoothCallback; import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.utils.ThreadUtils; import java.util.concurrent.Executor; import java.util.concurrent.Executors; public class AudioStreamsCategoryController extends PreferenceCategoryController { public class AudioStreamsCategoryController extends AudioSharingBasePreferenceController implements DefaultLifecycleObserver { private static final String TAG = "AudioStreamsCategoryController"; private static final boolean DEBUG = BluetoothUtils.D; private final LocalBluetoothManager mLocalBtManager; private final Executor mExecutor; private final BluetoothCallback mBluetoothCallback = new BluetoothCallback() { @Override public void onActiveDeviceChanged( @Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) { if (bluetoothProfile == BluetoothProfile.LE_AUDIO) { updateVisibility(isBroadcasting()); } } }; public AudioStreamsCategoryController(Context context, String key) { super(context, key); mLocalBtManager = Utils.getLocalBtManager(mContext); mExecutor = Executors.newSingleThreadExecutor(); } @Override public void onStart(@NonNull LifecycleOwner owner) { if (mLocalBtManager != null) { mLocalBtManager.getEventManager().registerCallback(mBluetoothCallback); } updateVisibility(isBroadcasting()); } @Override public void onStop(@NonNull LifecycleOwner owner) { if (mLocalBtManager != null) { mLocalBtManager.getEventManager().unregisterCallback(mBluetoothCallback); } } @Override Loading @@ -33,4 +82,23 @@ public class AudioStreamsCategoryController extends PreferenceCategoryController ? AVAILABLE : UNSUPPORTED_ON_DEVICE; } @Override public void updateVisibility(boolean isBroadcasting) { mExecutor.execute( () -> { boolean hasActiveLe = AudioSharingUtils.getActiveSinkOnAssistant(mLocalBtManager).isPresent(); if (DEBUG) { Log.d( TAG, "updateVisibility() isBroadcasting : " + isBroadcasting + " hasActiveLe : " + hasActiveLe); } ThreadUtils.postOnMainThread( () -> super.updateVisibility(hasActiveLe && !isBroadcasting)); }); } } Loading
src/com/android/settings/connecteddevice/audiosharing/AudioSharingBasePreferenceController.java +1 −1 Original line number Diff line number Diff line Loading @@ -64,7 +64,7 @@ public abstract class AudioSharingBasePreferenceController extends BasePreferenc mPreference.setVisible(isVisible); } private boolean isBroadcasting() { protected boolean isBroadcasting() { return mBroadcast != null && mBroadcast.isEnabled(null); } }
src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java +4 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.os.Bundle; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsCategoryController; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.widget.SettingsMainSwitchBar; Loading @@ -34,6 +35,7 @@ public class AudioSharingDashboardFragment extends DashboardFragment private AudioSharingDeviceVolumeGroupController mAudioSharingDeviceVolumeGroupController; private CallsAndAlarmsPreferenceController mCallsAndAlarmsPreferenceController; private AudioSharingNamePreferenceController mAudioSharingNamePreferenceController; private AudioStreamsCategoryController mAudioStreamsCategoryController; public AudioSharingDashboardFragment() { super(); Loading Loading @@ -73,6 +75,7 @@ public class AudioSharingDashboardFragment extends DashboardFragment mCallsAndAlarmsPreferenceController = use(CallsAndAlarmsPreferenceController.class); mCallsAndAlarmsPreferenceController.init(this); mAudioSharingNamePreferenceController = use(AudioSharingNamePreferenceController.class); mAudioStreamsCategoryController = use(AudioStreamsCategoryController.class); } @Override Loading @@ -98,5 +101,6 @@ public class AudioSharingDashboardFragment extends DashboardFragment mAudioSharingDeviceVolumeGroupController.updateVisibility(isVisible); mCallsAndAlarmsPreferenceController.updateVisibility(isVisible); mAudioSharingNamePreferenceController.updateVisibility(isVisible); mAudioStreamsCategoryController.updateVisibility(isVisible); } }
src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java +26 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; public class AudioSharingUtils { Loading Loading @@ -230,6 +231,31 @@ public class AudioSharingUtils { return false; } /** * Retrieves the one and only active Bluetooth LE Audio sink device, regardless if the device is * currently in an audio sharing session. * * @param manager The LocalBluetoothManager instance used to fetch connected devices. * @return An Optional containing the active LE Audio device, or an empty Optional if not found. */ public static Optional<CachedBluetoothDevice> getActiveSinkOnAssistant( LocalBluetoothManager manager) { if (manager == null) { Log.w(TAG, "getActiveSinksOnAssistant(): LocalBluetoothManager is null!"); return Optional.empty(); } var groupedDevices = AudioSharingUtils.fetchConnectedDevicesByGroupId(manager); var leadDevices = AudioSharingUtils.buildOrderedConnectedLeadDevices(manager, groupedDevices, false); if (!leadDevices.isEmpty() && AudioSharingUtils.isActiveLeAudioDevice(leadDevices.get(0))) { return Optional.of(leadDevices.get(0)); } else { Log.w(TAG, "getActiveSinksOnAssistant(): No active lead device!"); } return Optional.empty(); } /** Toast message on main thread. */ public static void toastMessage(Context context, String message) { ThreadUtils.postOnMainThread( Loading
src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsActiveDeviceSummaryUpdater.java +1 −21 Original line number Diff line number Diff line Loading @@ -30,8 +30,6 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.utils.ThreadUtils; import java.util.Optional; public class AudioStreamsActiveDeviceSummaryUpdater implements BluetoothCallback { private static final String TAG = "AudioStreamsActiveDeviceSummaryUpdater"; private static final boolean DEBUG = BluetoothUtils.D; Loading Loading @@ -82,31 +80,13 @@ public class AudioStreamsActiveDeviceSummaryUpdater implements BluetoothCallback } private String getSummary() { var activeSink = getActiveSinkOnAssistant(mBluetoothManager); var activeSink = AudioSharingUtils.getActiveSinkOnAssistant(mBluetoothManager); if (activeSink.isEmpty()) { return "No active LE Audio device"; } return activeSink.get().getName(); } private static Optional<CachedBluetoothDevice> getActiveSinkOnAssistant( LocalBluetoothManager manager) { if (manager == null) { Log.w(TAG, "getActiveSinksOnAssistant(): LocalBluetoothManager is null!"); return Optional.empty(); } var groupedDevices = AudioSharingUtils.fetchConnectedDevicesByGroupId(manager); var leadDevices = AudioSharingUtils.buildOrderedConnectedLeadDevices(manager, groupedDevices, false); if (!leadDevices.isEmpty() && AudioSharingUtils.isActiveLeAudioDevice(leadDevices.get(0))) { return Optional.of(leadDevices.get(0)); } else { Log.w(TAG, "getActiveSinksOnAssistant(): No active lead device!"); } return Optional.empty(); } /** Interface definition for a callback to be invoked when the summary has been changed. */ interface OnSummaryChangeListener { /** Loading
src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsCategoryController.java +70 −2 Original line number Diff line number Diff line Loading @@ -16,15 +16,64 @@ package com.android.settings.connecteddevice.audiosharing.audiostreams; import android.annotation.Nullable; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.util.Log; import androidx.annotation.NonNull; import androidx.lifecycle.DefaultLifecycleObserver; import androidx.lifecycle.LifecycleOwner; import com.android.settings.bluetooth.Utils; import com.android.settings.connecteddevice.audiosharing.AudioSharingBasePreferenceController; import com.android.settings.connecteddevice.audiosharing.AudioSharingUtils; import com.android.settings.flags.Flags; import com.android.settings.widget.PreferenceCategoryController; import com.android.settingslib.bluetooth.BluetoothCallback; import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.utils.ThreadUtils; import java.util.concurrent.Executor; import java.util.concurrent.Executors; public class AudioStreamsCategoryController extends PreferenceCategoryController { public class AudioStreamsCategoryController extends AudioSharingBasePreferenceController implements DefaultLifecycleObserver { private static final String TAG = "AudioStreamsCategoryController"; private static final boolean DEBUG = BluetoothUtils.D; private final LocalBluetoothManager mLocalBtManager; private final Executor mExecutor; private final BluetoothCallback mBluetoothCallback = new BluetoothCallback() { @Override public void onActiveDeviceChanged( @Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) { if (bluetoothProfile == BluetoothProfile.LE_AUDIO) { updateVisibility(isBroadcasting()); } } }; public AudioStreamsCategoryController(Context context, String key) { super(context, key); mLocalBtManager = Utils.getLocalBtManager(mContext); mExecutor = Executors.newSingleThreadExecutor(); } @Override public void onStart(@NonNull LifecycleOwner owner) { if (mLocalBtManager != null) { mLocalBtManager.getEventManager().registerCallback(mBluetoothCallback); } updateVisibility(isBroadcasting()); } @Override public void onStop(@NonNull LifecycleOwner owner) { if (mLocalBtManager != null) { mLocalBtManager.getEventManager().unregisterCallback(mBluetoothCallback); } } @Override Loading @@ -33,4 +82,23 @@ public class AudioStreamsCategoryController extends PreferenceCategoryController ? AVAILABLE : UNSUPPORTED_ON_DEVICE; } @Override public void updateVisibility(boolean isBroadcasting) { mExecutor.execute( () -> { boolean hasActiveLe = AudioSharingUtils.getActiveSinkOnAssistant(mLocalBtManager).isPresent(); if (DEBUG) { Log.d( TAG, "updateVisibility() isBroadcasting : " + isBroadcasting + " hasActiveLe : " + hasActiveLe); } ThreadUtils.postOnMainThread( () -> super.updateVisibility(hasActiveLe && !isBroadcasting)); }); } }