[Audiosharing] Hide / show audio streams category.

Only show when there is an active LE buds connecting, and the source is
not currently broadcasting.

Bug: 308368124
Test: Manual
Change-Id: I2cc172a66648901ac8a7e49c5aac734b6bbc7e33
This commit is contained in:
chelseahao
2023-11-23 15:42:28 +08:00
committed by Chelsea Hao
parent 40cc58f5a1
commit 78a667e7ca
5 changed files with 102 additions and 24 deletions

View File

@@ -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);
}
}

View File

@@ -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;
@@ -34,6 +35,7 @@ public class AudioSharingDashboardFragment extends DashboardFragment
private AudioSharingDeviceVolumeGroupController mAudioSharingDeviceVolumeGroupController;
private CallsAndAlarmsPreferenceController mCallsAndAlarmsPreferenceController;
private AudioSharingNamePreferenceController mAudioSharingNamePreferenceController;
private AudioStreamsCategoryController mAudioStreamsCategoryController;
public AudioSharingDashboardFragment() {
super();
@@ -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
@@ -98,5 +101,6 @@ public class AudioSharingDashboardFragment extends DashboardFragment
mAudioSharingDeviceVolumeGroupController.updateVisibility(isVisible);
mCallsAndAlarmsPreferenceController.updateVisibility(isVisible);
mAudioSharingNamePreferenceController.updateVisibility(isVisible);
mAudioStreamsCategoryController.updateVisibility(isVisible);
}
}

View File

@@ -34,6 +34,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 {
@@ -229,6 +230,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(

View File

@@ -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;
@@ -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 {
/**

View File

@@ -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;
public class AudioStreamsCategoryController extends PreferenceCategoryController {
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
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
@@ -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));
});
}
}