Merge "[Audiosharing] Reimpl audio sharing main switch" into main

This commit is contained in:
Yiyi Shen
2023-11-22 09:48:17 +00:00
committed by Android (Google) Code Review
3 changed files with 71 additions and 75 deletions

View File

@@ -46,4 +46,11 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center"/> 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> </LinearLayout>

View File

@@ -21,6 +21,7 @@ import android.app.settings.SettingsEnums;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
@@ -39,7 +40,7 @@ import java.util.Locale;
public class AudioSharingDialogFragment extends InstrumentedDialogFragment { public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
private static final String TAG = "AudioSharingDialog"; 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 // The host creates an instance of this dialog fragment must implement this interface to receive
// event callbacks. // event callbacks.
@@ -50,9 +51,6 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
* @param item The device item clicked. * @param item The device item clicked.
*/ */
void onItemClick(AudioSharingDeviceItem item); void onItemClick(AudioSharingDeviceItem item);
/** Called when users click the cancel button in the dialog. */
void onCancelClick();
} }
private static DialogEventListener sListener; private static DialogEventListener sListener;
@@ -68,6 +66,8 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
* Display the {@link AudioSharingDialogFragment} dialog. * Display the {@link AudioSharingDialogFragment} dialog.
* *
* @param host The Fragment this dialog will be hosted. * @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( public static void show(
Fragment host, Fragment host,
@@ -101,11 +101,6 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
subTitle1.setVisibility(View.INVISIBLE); subTitle1.setVisibility(View.INVISIBLE);
subTitle2.setText( subTitle2.setText(
"To start sharing audio, connect additional headphones that support LE audio"); "To start sharing audio, connect additional headphones that support LE audio");
builder.setNegativeButton(
"Close",
(dialog, which) -> {
sListener.onCancelClick();
});
} else { } else {
subTitle1.setText( subTitle1.setText(
String.format( String.format(
@@ -127,6 +122,8 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
})); }));
recyclerView.setLayoutManager( recyclerView.setLayoutManager(
new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false)); new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
Button cancelBtn = mRootView.findViewById(R.id.cancel_btn);
cancelBtn.setOnClickListener(v -> dismiss());
AlertDialog dialog = builder.setView(mRootView).create(); AlertDialog dialog = builder.setView(mRootView).create();
dialog.setCanceledOnTouchOutside(false); dialog.setCanceledOnTouchOutside(false);
return dialog; return dialog;

View File

@@ -35,7 +35,6 @@ import com.android.settings.core.BasePreferenceController;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.flags.Flags; import com.android.settings.flags.Flags;
import com.android.settings.widget.SettingsMainSwitchBar; import com.android.settings.widget.SettingsMainSwitchBar;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
@@ -44,8 +43,8 @@ import com.android.settingslib.utils.ThreadUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@@ -65,7 +64,6 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
private final Executor mExecutor; private final Executor mExecutor;
private final OnSwitchBarChangedListener mListener; private final OnSwitchBarChangedListener mListener;
private DashboardFragment mFragment; private DashboardFragment mFragment;
private List<BluetoothDevice> mTargetSinks = new ArrayList<>();
private final BluetoothLeBroadcast.Callback mBroadcastCallback = private final BluetoothLeBroadcast.Callback mBroadcastCallback =
new BluetoothLeBroadcast.Callback() { new BluetoothLeBroadcast.Callback() {
@@ -95,8 +93,45 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
"onBroadcastMetadataChanged(), broadcastId = " "onBroadcastMetadataChanged(), broadcastId = "
+ broadcastId + broadcastId
+ ", metadata = " + ", metadata = "
+ metadata); + metadata.getBroadcastName());
addSourceToTargetDevices(mTargetSinks); 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 @Override
@@ -172,6 +207,13 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
+ source + source
+ ", reason = " + ", reason = "
+ reason); + reason);
AudioSharingUtils.toastMessage(
mContext,
String.format(
Locale.US,
"Fail to add source to %s reason %d",
sink.getAddress(),
reason));
} }
@Override @Override
@@ -263,56 +305,8 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
mSwitchBar.setEnabled(true); mSwitchBar.setEnabled(true);
return; return;
} }
if (mFragment == null) { // TODO: start broadcast with new API
Log.w(TAG, "Dialog fail to show due to null fragment."); mBroadcast.startBroadcast("test", null);
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);
}
});
} }
private void stopAudioSharing() { private void stopAudioSharing() {
@@ -341,8 +335,8 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
return mBroadcast != null && mBroadcast.isEnabled(null); return mBroadcast != null && mBroadcast.isEnabled(null);
} }
private void addSourceToTargetDevices(List<BluetoothDevice> sinks) { private void addSourceToSink(BluetoothDevice sink) {
if (sinks.isEmpty() || mBroadcast == null || mAssistant == null) { if (mBroadcast == null || mAssistant == null) {
Log.d(TAG, "Skip adding source to target."); Log.d(TAG, "Skip adding source to target.");
return; return;
} }
@@ -352,7 +346,6 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
Log.e(TAG, "Error: There is no broadcastMetadata."); Log.e(TAG, "Error: There is no broadcastMetadata.");
return; return;
} }
for (BluetoothDevice sink : sinks) {
Log.d( Log.d(
TAG, TAG,
"Add broadcast with broadcastId: " "Add broadcast with broadcastId: "
@@ -361,5 +354,4 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
+ sink.getAnonymizedAddress()); + sink.getAnonymizedAddress());
mAssistant.addSource(sink, broadcastMetadata, /* isGroupOp= */ false); mAssistant.addSource(sink, broadcastMetadata, /* isGroupOp= */ false);
} }
}
} }