Merge "[Audiosharing] Reimpl audio sharing main switch" into main
This commit is contained in:
@@ -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>
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user