[Audiosharing] Reimpl audio sharing main switch
New flow: Automatically add sharing source to connected active device eligible for audio sharing. And then pop up the dialog for users to choose an additinal eligible device to share audio. Old flow: Pop up the dialog first and add sharing source after user interact to the dialog. Flagged with enable_le_audio_sharing Bug: 305620450 Test: Manual Change-Id: If0d1609b2677ca9ecae926c198f305fd1f4e34d3
This commit is contained in:
@@ -46,4 +46,11 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancel_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/cancel"/>
|
||||
</LinearLayout>
|
@@ -21,6 +21,7 @@ import android.app.settings.SettingsEnums;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
@@ -39,7 +40,7 @@ import java.util.Locale;
|
||||
public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
|
||||
private static final String TAG = "AudioSharingDialog";
|
||||
|
||||
private static final String BUNDLE_KEY_DEVICE_ITEMS = "bundle_key_device_names";
|
||||
private static final String BUNDLE_KEY_DEVICE_ITEMS = "bundle_key_device_items";
|
||||
|
||||
// The host creates an instance of this dialog fragment must implement this interface to receive
|
||||
// event callbacks.
|
||||
@@ -50,9 +51,6 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
|
||||
* @param item The device item clicked.
|
||||
*/
|
||||
void onItemClick(AudioSharingDeviceItem item);
|
||||
|
||||
/** Called when users click the cancel button in the dialog. */
|
||||
void onCancelClick();
|
||||
}
|
||||
|
||||
private static DialogEventListener sListener;
|
||||
@@ -68,6 +66,8 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
|
||||
* Display the {@link AudioSharingDialogFragment} dialog.
|
||||
*
|
||||
* @param host The Fragment this dialog will be hosted.
|
||||
* @param deviceItems The connected device items eligible for audio sharing.
|
||||
* @param listener The callback to handle the user action on this dialog.
|
||||
*/
|
||||
public static void show(
|
||||
Fragment host,
|
||||
@@ -101,11 +101,6 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
|
||||
subTitle1.setVisibility(View.INVISIBLE);
|
||||
subTitle2.setText(
|
||||
"To start sharing audio, connect additional headphones that support LE audio");
|
||||
builder.setNegativeButton(
|
||||
"Close",
|
||||
(dialog, which) -> {
|
||||
sListener.onCancelClick();
|
||||
});
|
||||
} else {
|
||||
subTitle1.setText(
|
||||
String.format(
|
||||
@@ -127,6 +122,8 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
|
||||
}));
|
||||
recyclerView.setLayoutManager(
|
||||
new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
|
||||
Button cancelBtn = mRootView.findViewById(R.id.cancel_btn);
|
||||
cancelBtn.setOnClickListener(v -> dismiss());
|
||||
AlertDialog dialog = builder.setView(mRootView).create();
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
return dialog;
|
||||
|
@@ -35,7 +35,6 @@ import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.widget.SettingsMainSwitchBar;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
|
||||
@@ -44,8 +43,8 @@ import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@@ -65,7 +64,6 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
||||
private final Executor mExecutor;
|
||||
private final OnSwitchBarChangedListener mListener;
|
||||
private DashboardFragment mFragment;
|
||||
private List<BluetoothDevice> mTargetSinks = new ArrayList<>();
|
||||
|
||||
private final BluetoothLeBroadcast.Callback mBroadcastCallback =
|
||||
new BluetoothLeBroadcast.Callback() {
|
||||
@@ -95,8 +93,45 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
||||
"onBroadcastMetadataChanged(), broadcastId = "
|
||||
+ broadcastId
|
||||
+ ", metadata = "
|
||||
+ metadata);
|
||||
addSourceToTargetDevices(mTargetSinks);
|
||||
+ metadata.getBroadcastName());
|
||||
Map<Integer, List<CachedBluetoothDevice>> groupedConnectedDevices =
|
||||
AudioSharingUtils.fetchConnectedDevicesByGroupId(mBtManager);
|
||||
ArrayList<AudioSharingDeviceItem> deviceItems =
|
||||
AudioSharingUtils.buildOrderedConnectedLeadAudioSharingDeviceItem(
|
||||
mBtManager,
|
||||
groupedConnectedDevices,
|
||||
/* filterByInSharing= */ false);
|
||||
// deviceItems is ordered. The active device is the first place if exits.
|
||||
ArrayList<AudioSharingDeviceItem> deviceItemsForSharing = deviceItems;
|
||||
if (!deviceItems.isEmpty() && deviceItems.get(0).isActive()) {
|
||||
for (CachedBluetoothDevice device :
|
||||
groupedConnectedDevices.get(deviceItems.get(0).getGroupId())) {
|
||||
// If active device exists for audio sharing, share to it
|
||||
// automatically once the broadcast is started.
|
||||
addSourceToSink(device.getDevice());
|
||||
}
|
||||
deviceItemsForSharing.remove(0);
|
||||
}
|
||||
if (mFragment == null) {
|
||||
Log.w(TAG, "Dialog fail to show due to null fragment.");
|
||||
return;
|
||||
}
|
||||
ThreadUtils.postOnMainThread(
|
||||
() -> {
|
||||
AudioSharingDialogFragment.show(
|
||||
mFragment,
|
||||
deviceItemsForSharing,
|
||||
item -> {
|
||||
if (groupedConnectedDevices.containsKey(
|
||||
item.getGroupId())) {
|
||||
for (CachedBluetoothDevice device :
|
||||
groupedConnectedDevices.get(
|
||||
item.getGroupId())) {
|
||||
addSourceToSink(device.getDevice());
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -172,6 +207,13 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
||||
+ source
|
||||
+ ", reason = "
|
||||
+ reason);
|
||||
AudioSharingUtils.toastMessage(
|
||||
mContext,
|
||||
String.format(
|
||||
Locale.US,
|
||||
"Fail to add source to %s reason %d",
|
||||
sink.getAddress(),
|
||||
reason));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -263,56 +305,8 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
||||
mSwitchBar.setEnabled(true);
|
||||
return;
|
||||
}
|
||||
if (mFragment == null) {
|
||||
Log.w(TAG, "Dialog fail to show due to null fragment.");
|
||||
mSwitchBar.setEnabled(true);
|
||||
return;
|
||||
}
|
||||
Map<Integer, List<CachedBluetoothDevice>> groupedDevices =
|
||||
AudioSharingUtils.fetchConnectedDevicesByGroupId(mBtManager);
|
||||
ArrayList<AudioSharingDeviceItem> deviceItems = new ArrayList<>();
|
||||
Optional<Integer> activeGroupId = Optional.empty();
|
||||
for (List<CachedBluetoothDevice> devices : groupedDevices.values()) {
|
||||
// Use random device in the group to represent the group.
|
||||
CachedBluetoothDevice device = devices.get(0);
|
||||
if (BluetoothUtils.isActiveLeAudioDevice(device)) {
|
||||
activeGroupId = Optional.of(device.getGroupId());
|
||||
} else {
|
||||
AudioSharingDeviceItem item = AudioSharingUtils.buildAudioSharingDeviceItem(device);
|
||||
deviceItems.add(item);
|
||||
}
|
||||
}
|
||||
mTargetSinks = new ArrayList<>();
|
||||
activeGroupId.ifPresent(
|
||||
gId -> {
|
||||
if (groupedDevices.containsKey(gId)) {
|
||||
for (CachedBluetoothDevice device : groupedDevices.get(gId)) {
|
||||
mTargetSinks.add(device.getDevice());
|
||||
}
|
||||
}
|
||||
});
|
||||
AudioSharingDialogFragment.show(
|
||||
mFragment,
|
||||
deviceItems,
|
||||
new AudioSharingDialogFragment.DialogEventListener() {
|
||||
@Override
|
||||
public void onItemClick(AudioSharingDeviceItem item) {
|
||||
if (groupedDevices.containsKey(item.getGroupId())) {
|
||||
for (CachedBluetoothDevice device :
|
||||
groupedDevices.get(item.getGroupId())) {
|
||||
mTargetSinks.add(device.getDevice());
|
||||
}
|
||||
}
|
||||
// TODO: handle app source name for broadcasting.
|
||||
mBroadcast.startBroadcast("test", /* language= */ null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelClick() {
|
||||
// TODO: handle app source name for broadcasting.
|
||||
mBroadcast.startBroadcast("test", /* language= */ null);
|
||||
}
|
||||
});
|
||||
// TODO: start broadcast with new API
|
||||
mBroadcast.startBroadcast("test", null);
|
||||
}
|
||||
|
||||
private void stopAudioSharing() {
|
||||
@@ -341,8 +335,8 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
||||
return mBroadcast != null && mBroadcast.isEnabled(null);
|
||||
}
|
||||
|
||||
private void addSourceToTargetDevices(List<BluetoothDevice> sinks) {
|
||||
if (sinks.isEmpty() || mBroadcast == null || mAssistant == null) {
|
||||
private void addSourceToSink(BluetoothDevice sink) {
|
||||
if (mBroadcast == null || mAssistant == null) {
|
||||
Log.d(TAG, "Skip adding source to target.");
|
||||
return;
|
||||
}
|
||||
@@ -352,7 +346,6 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
||||
Log.e(TAG, "Error: There is no broadcastMetadata.");
|
||||
return;
|
||||
}
|
||||
for (BluetoothDevice sink : sinks) {
|
||||
Log.d(
|
||||
TAG,
|
||||
"Add broadcast with broadcastId: "
|
||||
@@ -362,4 +355,3 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
||||
mAssistant.addSource(sink, broadcastMetadata, /* isGroupOp= */ false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user