[Audiosharing] Avoid dialog flickering for same bt device group.
Before this change, the dialog will dismiss and show up again if the
second bud of the same group is connected.
In this change, StopDialog and JoinDialog will only update the message
and event listener when the dialog is triggered by another device with the same group id or the new bt device with different group id. (No dismiss and show); DisconnectDialog will only dismiss and show again when a new bt device with different group id is connected and update the event listener when another device with the same group id connected.
Also dismiss the dialog when the triggering device disconnect or join
the sharing.
Test: atest
Bug: 305620450
Change-Id: I798812101cefb24185d76d56f78eae27712dd7a6
diff --git a/res/layout/dialog_audio_sharing_join.xml b/res/layout/dialog_audio_sharing_join.xml
index 4bdab7f..bfd4c77 100644
--- a/res/layout/dialog_audio_sharing_join.xml
+++ b/res/layout/dialog_audio_sharing_join.xml
@@ -24,16 +24,7 @@
android:paddingBottom="?android:dialogPreferredPadding">
<TextView
- android:id="@+id/share_audio_subtitle1"
- style="@style/DeviceAudioSharingText"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:paddingBottom="14dp"
- android:textFontWeight="500" />
-
- <TextView
- android:id="@+id/share_audio_subtitle2"
+ android:id="@+id/share_audio_subtitle"
style="@style/DeviceAudioSharingText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
index 3fd5127..ef0f226 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
@@ -17,6 +17,7 @@
package com.android.settings.connecteddevice.audiosharing;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcast;
import android.bluetooth.BluetoothLeBroadcastAssistant;
@@ -27,6 +28,7 @@
import android.util.Log;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.DefaultLifecycleObserver;
@@ -43,6 +45,7 @@
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.LeAudioProfile;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
@@ -68,9 +71,10 @@
"connected_device_audio_sharing_settings";
private final LocalBluetoothManager mLocalBtManager;
- private final LocalBluetoothLeBroadcast mBroadcast;
- private final LocalBluetoothLeBroadcastAssistant mAssistant;
private final Executor mExecutor;
+ private CachedBluetoothDeviceManager mDeviceManager;
+ private LocalBluetoothLeBroadcast mBroadcast;
+ private LocalBluetoothLeBroadcastAssistant mAssistant;
private PreferenceGroup mPreferenceGroup;
private Preference mAudioSharingSettingsPreference;
private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
@@ -165,6 +169,12 @@
+ ", reason = "
+ reason);
mBluetoothDeviceUpdater.forceUpdate();
+ if (mDeviceManager != null) {
+ CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(sink);
+ if (cachedDevice != null) {
+ closeOpeningDialogsForLeaDevice(cachedDevice);
+ }
+ }
}
@Override
@@ -241,8 +251,11 @@
public AudioSharingDevicePreferenceController(Context context) {
super(context, KEY);
mLocalBtManager = Utils.getLocalBtManager(mContext);
- mBroadcast = mLocalBtManager.getProfileManager().getLeAudioBroadcastProfile();
- mAssistant = mLocalBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile();
+ if (mLocalBtManager != null) {
+ mDeviceManager = mLocalBtManager.getCachedDeviceManager();
+ mBroadcast = mLocalBtManager.getProfileManager().getLeAudioBroadcastProfile();
+ mAssistant = mLocalBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile();
+ }
mExecutor = Executors.newSingleThreadExecutor();
}
@@ -344,6 +357,17 @@
@NonNull CachedBluetoothDevice cachedDevice,
@ConnectionState int state,
int bluetoothProfile) {
+ if (state == BluetoothAdapter.STATE_DISCONNECTED) {
+ boolean isLeAudio = isLeAudioSupported(cachedDevice);
+ if (isLeAudio && bluetoothProfile == BluetoothProfile.LE_AUDIO) {
+ closeOpeningDialogsForLeaDevice(cachedDevice);
+ return;
+ }
+ if (!isLeAudio && !cachedDevice.isConnected()) {
+ closeOpeningDialogsForNonLeaDevice(cachedDevice);
+ return;
+ }
+ }
if (state != BluetoothAdapter.STATE_CONNECTED || !cachedDevice.getDevice().isConnected()) {
Log.d(TAG, "Ignore onProfileConnectionStateChanged, not connected state");
return;
@@ -420,10 +444,10 @@
// connected during a sharing session.
postOnMainThread(
() -> {
- closeOpeningDialogs();
+ closeOpeningDialogsOtherThan(AudioSharingStopDialogFragment.tag());
AudioSharingStopDialogFragment.show(
mFragment,
- cachedDevice.getName(),
+ cachedDevice,
() -> mBroadcast.stopBroadcast(mBroadcast.getLatestBroadcastId()));
});
} else {
@@ -466,11 +490,12 @@
if (deviceItemsInSharingSession.size() >= 2) {
postOnMainThread(
() -> {
- closeOpeningDialogs();
+ closeOpeningDialogsOtherThan(
+ AudioSharingDisconnectDialogFragment.tag());
AudioSharingDisconnectDialogFragment.show(
mFragment,
deviceItemsInSharingSession,
- cachedDevice.getName(),
+ cachedDevice,
(AudioSharingDeviceItem item) -> {
// Remove all sources from the device user clicked
if (groupedDevices.containsKey(item.getGroupId())) {
@@ -497,11 +522,11 @@
// remote device connected during a sharing session.
postOnMainThread(
() -> {
- closeOpeningDialogs();
+ closeOpeningDialogsOtherThan(AudioSharingJoinDialogFragment.tag());
AudioSharingJoinDialogFragment.show(
mFragment,
deviceItemsInSharingSession,
- cachedDevice.getName(),
+ cachedDevice,
() -> {
// Add current broadcast to the latest connected device
mAssistant.addSource(
@@ -527,11 +552,11 @@
if (deviceItems.size() == 1) {
postOnMainThread(
() -> {
- closeOpeningDialogs();
+ closeOpeningDialogsOtherThan(AudioSharingJoinDialogFragment.tag());
AudioSharingJoinDialogFragment.show(
mFragment,
deviceItems,
- cachedDevice.getName(),
+ cachedDevice,
() -> {
mTargetSinks = new ArrayList<>();
for (List<CachedBluetoothDevice> devices :
@@ -591,17 +616,61 @@
}
}
- private void closeOpeningDialogs() {
+ private void closeOpeningDialogsOtherThan(String tag) {
if (mFragment == null) return;
List<Fragment> fragments = mFragment.getChildFragmentManager().getFragments();
for (Fragment fragment : fragments) {
- if (fragment instanceof DialogFragment) {
+ if (fragment instanceof DialogFragment && !fragment.getTag().equals(tag)) {
Log.d(TAG, "Remove staled opening dialog " + fragment.getTag());
((DialogFragment) fragment).dismiss();
}
}
}
+ private void closeOpeningDialogsForLeaDevice(@NonNull CachedBluetoothDevice cachedDevice) {
+ if (mFragment == null) return;
+ int groupId = AudioSharingUtils.getGroupId(cachedDevice);
+ List<Fragment> fragments = mFragment.getChildFragmentManager().getFragments();
+ for (Fragment fragment : fragments) {
+ CachedBluetoothDevice device = getCachedBluetoothDeviceFromDialog(fragment);
+ if (device != null
+ && groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID
+ && AudioSharingUtils.getGroupId(device) == groupId) {
+ Log.d(TAG, "Remove staled opening dialog for group " + groupId);
+ ((DialogFragment) fragment).dismiss();
+ }
+ }
+ }
+
+ private void closeOpeningDialogsForNonLeaDevice(@NonNull CachedBluetoothDevice cachedDevice) {
+ if (mFragment == null) return;
+ String address = cachedDevice.getAddress();
+ List<Fragment> fragments = mFragment.getChildFragmentManager().getFragments();
+ for (Fragment fragment : fragments) {
+ CachedBluetoothDevice device = getCachedBluetoothDeviceFromDialog(fragment);
+ if (device != null && address != null && address.equals(device.getAddress())) {
+ Log.d(
+ TAG,
+ "Remove staled opening dialog for device "
+ + cachedDevice.getDevice().getAnonymizedAddress());
+ ((DialogFragment) fragment).dismiss();
+ }
+ }
+ }
+
+ @Nullable
+ private CachedBluetoothDevice getCachedBluetoothDeviceFromDialog(Fragment fragment) {
+ CachedBluetoothDevice device = null;
+ if (fragment instanceof AudioSharingJoinDialogFragment) {
+ device = ((AudioSharingJoinDialogFragment) fragment).getDevice();
+ } else if (fragment instanceof AudioSharingStopDialogFragment) {
+ device = ((AudioSharingStopDialogFragment) fragment).getDevice();
+ } else if (fragment instanceof AudioSharingDisconnectDialogFragment) {
+ device = ((AudioSharingDisconnectDialogFragment) fragment).getDevice();
+ }
+ return device;
+ }
+
private void postOnMainThread(@NonNull Runnable runnable) {
mContext.getMainExecutor().execute(runnable);
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragment.java
index a2b1824..74c73aa 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragment.java
@@ -19,13 +19,17 @@
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.os.Bundle;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.LinearLayoutManager;
@@ -33,8 +37,10 @@
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import java.util.ArrayList;
+import java.util.Locale;
public class AudioSharingDisconnectDialogFragment extends InstrumentedDialogFragment {
private static final String TAG = "AudioSharingDisconnectDialog";
@@ -56,6 +62,7 @@
}
private static DialogEventListener sListener;
+ @Nullable private static CachedBluetoothDevice sNewDevice;
@Override
public int getMetricsCategory() {
@@ -65,35 +72,78 @@
/**
* Display the {@link AudioSharingDisconnectDialogFragment} dialog.
*
+ * <p>If the dialog is showing for the same group, update the dialog event listener.
+ *
* @param host The Fragment this dialog will be hosted.
* @param deviceItems The existing connected device items in audio sharing session.
- * @param newDeviceName The name of the latest connected device triggered this dialog.
+ * @param newDevice The latest connected device triggered this dialog.
* @param listener The callback to handle the user action on this dialog.
*/
public static void show(
Fragment host,
ArrayList<AudioSharingDeviceItem> deviceItems,
- String newDeviceName,
+ CachedBluetoothDevice newDevice,
DialogEventListener listener) {
if (!AudioSharingUtils.isFeatureEnabled()) return;
final FragmentManager manager = host.getChildFragmentManager();
+ Fragment dialog = manager.findFragmentByTag(TAG);
+ if (dialog != null
+ && ((DialogFragment) dialog).getDialog() != null
+ && ((DialogFragment) dialog).getDialog().isShowing()) {
+ int newGroupId = AudioSharingUtils.getGroupId(newDevice);
+ if (sNewDevice != null && newGroupId == AudioSharingUtils.getGroupId(sNewDevice)) {
+ Log.d(
+ TAG,
+ String.format(
+ Locale.US,
+ "Dialog is showing for the same device group %d, "
+ + "update the content.",
+ newGroupId));
+ sListener = listener;
+ sNewDevice = newDevice;
+ return;
+ } else {
+ Log.d(
+ TAG,
+ String.format(
+ Locale.US,
+ "Dialog is showing for new device group %d, "
+ + "dismiss current dialog.",
+ newGroupId));
+ ((DialogFragment) dialog).dismiss();
+ }
+ }
sListener = listener;
+ sNewDevice = newDevice;
+ Log.d(TAG, "Show up the dialog.");
final Bundle bundle = new Bundle();
bundle.putParcelableArrayList(BUNDLE_KEY_DEVICE_TO_DISCONNECT_ITEMS, deviceItems);
- bundle.putString(BUNDLE_KEY_NEW_DEVICE_NAME, newDeviceName);
- AudioSharingDisconnectDialogFragment dialog = new AudioSharingDisconnectDialogFragment();
- dialog.setArguments(bundle);
- dialog.show(manager, TAG);
+ bundle.putString(BUNDLE_KEY_NEW_DEVICE_NAME, newDevice.getName());
+ AudioSharingDisconnectDialogFragment dialogFrag =
+ new AudioSharingDisconnectDialogFragment();
+ dialogFrag.setArguments(bundle);
+ dialogFrag.show(manager, TAG);
+ }
+
+ /** Return the tag of {@link AudioSharingDisconnectDialogFragment} dialog. */
+ public static @NonNull String tag() {
+ return TAG;
+ }
+
+ /** Get the latest connected device which triggers the dialog. */
+ public @Nullable CachedBluetoothDevice getDevice() {
+ return sNewDevice;
}
@Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
Bundle arguments = requireArguments();
ArrayList<AudioSharingDeviceItem> deviceItems =
arguments.getParcelableArrayList(BUNDLE_KEY_DEVICE_TO_DISCONNECT_ITEMS);
final AlertDialog.Builder builder =
new AlertDialog.Builder(getActivity()).setCancelable(false);
LayoutInflater inflater = LayoutInflater.from(builder.getContext());
+ // Set custom title for the dialog.
View customTitle = inflater.inflate(R.layout.dialog_custom_title_audio_sharing, null);
ImageView icon = customTitle.findViewById(R.id.title_icon);
icon.setImageResource(R.drawable.ic_bt_audio_sharing);
@@ -115,10 +165,7 @@
recyclerView.setLayoutManager(
new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
Button cancelBtn = rootView.findViewById(R.id.cancel_btn);
- cancelBtn.setOnClickListener(
- v -> {
- dismiss();
- });
+ cancelBtn.setOnClickListener(v -> dismiss());
AlertDialog dialog = builder.setCustomTitle(customTitle).setView(rootView).create();
dialog.setCanceledOnTouchOutside(false);
return dialog;
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragment.java
index f3f0fe4..8791c11 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragment.java
@@ -18,19 +18,25 @@
import android.app.Dialog;
import android.app.settings.SettingsEnums;
+import android.graphics.Typeface;
import android.os.Bundle;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import java.util.ArrayList;
import java.util.Locale;
@@ -49,6 +55,7 @@
}
private static DialogEventListener sListener;
+ private static @Nullable CachedBluetoothDevice sNewDevice;
@Override
public int getMetricsCategory() {
@@ -58,29 +65,54 @@
/**
* Display the {@link AudioSharingJoinDialogFragment} dialog.
*
+ * <p>If the dialog is showing, update the dialog message and event listener.
+ *
* @param host The Fragment this dialog will be hosted.
* @param deviceItems The existing connected device items eligible for audio sharing.
- * @param newDeviceName The name of the latest connected device triggered this dialog.
+ * @param newDevice The latest connected device triggered this dialog.
* @param listener The callback to handle the user action on this dialog.
*/
public static void show(
Fragment host,
ArrayList<AudioSharingDeviceItem> deviceItems,
- String newDeviceName,
+ CachedBluetoothDevice newDevice,
DialogEventListener listener) {
if (!AudioSharingUtils.isFeatureEnabled()) return;
final FragmentManager manager = host.getChildFragmentManager();
sListener = listener;
- final Bundle bundle = new Bundle();
- bundle.putParcelableArrayList(BUNDLE_KEY_DEVICE_ITEMS, deviceItems);
- bundle.putString(BUNDLE_KEY_NEW_DEVICE_NAME, newDeviceName);
- final AudioSharingJoinDialogFragment dialog = new AudioSharingJoinDialogFragment();
- dialog.setArguments(bundle);
- dialog.show(manager, TAG);
+ sNewDevice = newDevice;
+ Fragment dialog = manager.findFragmentByTag(TAG);
+ if (dialog != null
+ && ((DialogFragment) dialog).getDialog() != null
+ && ((DialogFragment) dialog).getDialog().isShowing()) {
+ Log.d(TAG, "Dialog is showing, update the content.");
+ updateDialog(
+ deviceItems,
+ newDevice.getName(),
+ (AlertDialog) ((DialogFragment) dialog).getDialog());
+ } else {
+ Log.d(TAG, "Show up the dialog.");
+ final Bundle bundle = new Bundle();
+ bundle.putParcelableArrayList(BUNDLE_KEY_DEVICE_ITEMS, deviceItems);
+ bundle.putString(BUNDLE_KEY_NEW_DEVICE_NAME, newDevice.getName());
+ final AudioSharingJoinDialogFragment dialogFrag = new AudioSharingJoinDialogFragment();
+ dialogFrag.setArguments(bundle);
+ dialogFrag.show(manager, TAG);
+ }
+ }
+
+ /** Return the tag of {@link AudioSharingJoinDialogFragment} dialog. */
+ public static @NonNull String tag() {
+ return TAG;
+ }
+
+ /** Get the latest connected device which triggers the dialog. */
+ public @Nullable CachedBluetoothDevice getDevice() {
+ return sNewDevice;
}
@Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
Bundle arguments = requireArguments();
ArrayList<AudioSharingDeviceItem> deviceItems =
arguments.getParcelableArrayList(BUNDLE_KEY_DEVICE_ITEMS);
@@ -88,6 +120,7 @@
final AlertDialog.Builder builder =
new AlertDialog.Builder(getActivity()).setCancelable(false);
LayoutInflater inflater = LayoutInflater.from(builder.getContext());
+ // Set custom title for the dialog.
View customTitle =
inflater.inflate(R.layout.dialog_custom_title_audio_sharing, /* parent= */ null);
ImageView icon = customTitle.findViewById(R.id.title_icon);
@@ -95,21 +128,8 @@
TextView title = customTitle.findViewById(R.id.title_text);
title.setText("Share your audio");
View rootView = inflater.inflate(R.layout.dialog_audio_sharing_join, /* parent= */ null);
- TextView subtitle1 = rootView.findViewById(R.id.share_audio_subtitle1);
- TextView subtitle2 = rootView.findViewById(R.id.share_audio_subtitle2);
- if (deviceItems.isEmpty()) {
- subtitle1.setText(newDeviceName);
- } else {
- subtitle1.setText(
- String.format(
- Locale.US,
- "%s and %s",
- deviceItems.stream()
- .map(AudioSharingDeviceItem::getName)
- .collect(Collectors.joining(", ")),
- newDeviceName));
- }
- subtitle2.setText("This device's music and videos will play on both pairs of headphones");
+ TextView subtitle = rootView.findViewById(R.id.share_audio_subtitle);
+ subtitle.setText("This device's music and videos will play on both pairs of headphones");
Button shareBtn = rootView.findViewById(R.id.share_btn);
Button cancelBtn = rootView.findViewById(R.id.cancel_btn);
shareBtn.setOnClickListener(
@@ -119,8 +139,37 @@
});
shareBtn.setText("Share audio");
cancelBtn.setOnClickListener(v -> dismiss());
- Dialog dialog = builder.setCustomTitle(customTitle).setView(rootView).create();
+ AlertDialog dialog = builder.setCustomTitle(customTitle).setView(rootView).create();
dialog.setCanceledOnTouchOutside(false);
+ updateDialog(deviceItems, newDeviceName, dialog);
+ dialog.show();
+ TextView messageView = (TextView) dialog.findViewById(android.R.id.message);
+ if (messageView != null) {
+ Typeface typeface = Typeface.create(Typeface.DEFAULT_FAMILY, Typeface.NORMAL);
+ messageView.setTypeface(typeface);
+ messageView.setTextDirection(View.TEXT_DIRECTION_LOCALE);
+ messageView.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
+ } else {
+ Log.w(TAG, "Fail to update message style: message view is null");
+ }
return dialog;
}
+
+ private static void updateDialog(
+ ArrayList<AudioSharingDeviceItem> deviceItems,
+ String newDeviceName,
+ @NonNull AlertDialog dialog) {
+ if (deviceItems.isEmpty()) {
+ dialog.setMessage(newDeviceName);
+ } else {
+ dialog.setMessage(
+ String.format(
+ Locale.US,
+ "%s and %s",
+ deviceItems.stream()
+ .map(AudioSharingDeviceItem::getName)
+ .collect(Collectors.joining(", ")),
+ newDeviceName));
+ }
+ }
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragment.java
index 1454f76..3ba41f7 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragment.java
@@ -18,18 +18,24 @@
import android.app.Dialog;
import android.app.settings.SettingsEnums;
+import android.graphics.Typeface;
import android.os.Bundle;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
public class AudioSharingStopDialogFragment extends InstrumentedDialogFragment {
private static final String TAG = "AudioSharingStopDialog";
@@ -44,6 +50,7 @@
}
private static DialogEventListener sListener;
+ private static @Nullable CachedBluetoothDevice sNewDevice;
@Override
public int getMetricsCategory() {
@@ -53,41 +60,79 @@
/**
* Display the {@link AudioSharingStopDialogFragment} dialog.
*
+ * <p>If the dialog is showing, update the dialog message and event listener.
+ *
* @param host The Fragment this dialog will be hosted.
- * @param newDeviceName The name of the latest connected device triggered this dialog.
+ * @param newDevice The latest connected device triggered this dialog.
* @param listener The callback to handle the user action on this dialog.
*/
- public static void show(Fragment host, String newDeviceName, DialogEventListener listener) {
+ public static void show(
+ Fragment host, CachedBluetoothDevice newDevice, DialogEventListener listener) {
if (!AudioSharingUtils.isFeatureEnabled()) return;
final FragmentManager manager = host.getChildFragmentManager();
sListener = listener;
- final Bundle bundle = new Bundle();
- bundle.putString(BUNDLE_KEY_NEW_DEVICE_NAME, newDeviceName);
- AudioSharingStopDialogFragment dialog = new AudioSharingStopDialogFragment();
- dialog.setArguments(bundle);
- dialog.show(manager, TAG);
+ sNewDevice = newDevice;
+ Fragment dialog = manager.findFragmentByTag(TAG);
+ if (dialog != null
+ && ((DialogFragment) dialog).getDialog() != null
+ && ((DialogFragment) dialog).getDialog().isShowing()) {
+ Log.d(TAG, "Dialog is showing, update the content.");
+ updateDialog(newDevice.getName(), (AlertDialog) ((DialogFragment) dialog).getDialog());
+ } else {
+ Log.d(TAG, "Show up the dialog.");
+ final Bundle bundle = new Bundle();
+ bundle.putString(BUNDLE_KEY_NEW_DEVICE_NAME, newDevice.getName());
+ AudioSharingStopDialogFragment dialogFrag = new AudioSharingStopDialogFragment();
+ dialogFrag.setArguments(bundle);
+ dialogFrag.show(manager, TAG);
+ }
+ }
+
+ /** Return the tag of {@link AudioSharingStopDialogFragment} dialog. */
+ public static @NonNull String tag() {
+ return TAG;
+ }
+
+ /** Get the latest connected device which triggers the dialog. */
+ public @Nullable CachedBluetoothDevice getDevice() {
+ return sNewDevice;
}
@Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
Bundle arguments = requireArguments();
String newDeviceName = arguments.getString(BUNDLE_KEY_NEW_DEVICE_NAME);
final AlertDialog.Builder builder =
new AlertDialog.Builder(getActivity()).setCancelable(false);
LayoutInflater inflater = LayoutInflater.from(builder.getContext());
+ // Set custom title for the dialog.
View customTitle =
inflater.inflate(R.layout.dialog_custom_title_audio_sharing, /* parent= */ null);
ImageView icon = customTitle.findViewById(R.id.title_icon);
icon.setImageResource(R.drawable.ic_warning_24dp);
TextView title = customTitle.findViewById(R.id.title_text);
title.setText("Stop sharing audio?");
- builder.setMessage(
- newDeviceName + " wants to connect, headphones in audio sharing will disconnect.");
builder.setPositiveButton(
"Stop sharing", (dialog, which) -> sListener.onStopSharingClick());
builder.setNegativeButton("Cancel", (dialog, which) -> dismiss());
AlertDialog dialog = builder.setCustomTitle(customTitle).create();
dialog.setCanceledOnTouchOutside(false);
+ updateDialog(newDeviceName, dialog);
+ dialog.show();
+ TextView messageView = (TextView) dialog.findViewById(android.R.id.message);
+ if (messageView != null) {
+ Typeface typeface = Typeface.create(Typeface.DEFAULT_FAMILY, Typeface.NORMAL);
+ messageView.setTypeface(typeface);
+ messageView.setTextDirection(View.TEXT_DIRECTION_LOCALE);
+ messageView.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
+ } else {
+ Log.w(TAG, "sssFail to update dialog: message view is null");
+ }
return dialog;
}
+
+ private static void updateDialog(String newDeviceName, @NonNull AlertDialog dialog) {
+ dialog.setMessage(
+ newDeviceName + " wants to connect, headphones in audio sharing will disconnect.");
+ }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragmentTest.java
index 335bbe3..966a695 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragmentTest.java
@@ -18,15 +18,18 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothStatusCodes;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.view.View;
+import android.widget.Button;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
@@ -37,11 +40,13 @@
import com.android.settings.flags.Flags;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
@@ -50,6 +55,7 @@
import org.robolectric.shadows.androidx.fragment.FragmentController;
import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicBoolean;
@RunWith(RobolectricTestRunner.class)
@Config(
@@ -67,38 +73,68 @@
private static final String TEST_DEVICE_NAME1 = "test1";
private static final String TEST_DEVICE_NAME2 = "test2";
private static final String TEST_DEVICE_NAME3 = "test3";
+ private static final int TEST_GROUP_ID1 = 1;
+ private static final int TEST_GROUP_ID2 = 2;
+ private static final int TEST_GROUP_ID3 = 3;
private static final AudioSharingDeviceItem TEST_DEVICE_ITEM1 =
- new AudioSharingDeviceItem(TEST_DEVICE_NAME1, /* groupId= */ 1, /* isActive= */ true);
+ new AudioSharingDeviceItem(TEST_DEVICE_NAME1, TEST_GROUP_ID1, /* isActive= */ true);
private static final AudioSharingDeviceItem TEST_DEVICE_ITEM2 =
- new AudioSharingDeviceItem(TEST_DEVICE_NAME2, /* groupId= */ 2, /* isActive= */ false);
+ new AudioSharingDeviceItem(TEST_DEVICE_NAME2, TEST_GROUP_ID2, /* isActive= */ false);
+ private static final AudioSharingDeviceItem TEST_DEVICE_ITEM3 =
+ new AudioSharingDeviceItem(TEST_DEVICE_NAME3, TEST_GROUP_ID3, /* isActive= */ false);
+ @Mock private BluetoothDevice mDevice1;
+ @Mock private BluetoothDevice mDevice2;
+ @Mock private BluetoothDevice mDevice3;
+
+ @Mock private CachedBluetoothDevice mCachedDevice1;
+ @Mock private CachedBluetoothDevice mCachedDevice2;
+ @Mock private CachedBluetoothDevice mCachedDevice3;
private Fragment mParent;
private AudioSharingDisconnectDialogFragment mFragment;
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+ private ArrayList<AudioSharingDeviceItem> mDeviceItems = new ArrayList<>();
@Before
public void setUp() {
- ShadowAlertDialogCompat.reset();
+ AlertDialog latestAlertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ if (latestAlertDialog != null) {
+ latestAlertDialog.dismiss();
+ ShadowAlertDialogCompat.reset();
+ }
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
mShadowBluetoothAdapter.setEnabled(true);
mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
+ when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
+ when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
+ when(mCachedDevice1.getGroupId()).thenReturn(TEST_GROUP_ID1);
+ when(mCachedDevice2.getName()).thenReturn(TEST_DEVICE_NAME2);
+ when(mCachedDevice2.getDevice()).thenReturn(mDevice2);
+ when(mCachedDevice2.getGroupId()).thenReturn(TEST_GROUP_ID2);
+ when(mCachedDevice3.getName()).thenReturn(TEST_DEVICE_NAME3);
+ when(mCachedDevice3.getDevice()).thenReturn(mDevice3);
+ when(mCachedDevice3.getGroupId()).thenReturn(TEST_GROUP_ID3);
mFragment = new AudioSharingDisconnectDialogFragment();
mParent = new Fragment();
FragmentController.setupFragment(
mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null);
- ArrayList<AudioSharingDeviceItem> list = new ArrayList<>();
- list.add(TEST_DEVICE_ITEM1);
- list.add(TEST_DEVICE_ITEM2);
- mFragment.show(mParent, list, TEST_DEVICE_NAME3, (item) -> {});
+ mDeviceItems.add(TEST_DEVICE_ITEM1);
+ mDeviceItems.add(TEST_DEVICE_ITEM2);
+ mFragment.show(mParent, mDeviceItems, mCachedDevice3, (item) -> {});
shadowMainLooper().idle();
}
@Test
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onCreateDialog_flagOff_dialogNotExist() {
+ ArrayList<AudioSharingDeviceItem> list = new ArrayList<>();
+ list.add(TEST_DEVICE_ITEM1);
+ list.add(TEST_DEVICE_ITEM2);
+ mFragment.show(mParent, list, mCachedDevice3, (item) -> {});
+ shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNull();
}
@@ -107,6 +143,7 @@
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onCreateDialog_flagOn_dialogShowBtnForTwoDevices() {
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog.isShowing()).isTrue();
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
View rootView = shadowDialog.getView();
RecyclerView view = rootView.findViewById(R.id.device_btn_list);
@@ -115,8 +152,70 @@
@Test
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
+ public void onCreateDialog_dialogIsShowingForSameGroup_updateDialog() {
+ String prefix = "Disconnect ";
+ AtomicBoolean isItemBtnClicked = new AtomicBoolean(false);
+ AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog.isShowing()).isTrue();
+ ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
+ View rootView = shadowDialog.getView();
+ RecyclerView view = rootView.findViewById(R.id.device_btn_list);
+ assertThat(view.getAdapter().getItemCount()).isEqualTo(2);
+ Button btn1 =
+ view.findViewHolderForAdapterPosition(0).itemView.findViewById(R.id.device_button);
+ assertThat(btn1.getText().toString()).isEqualTo(prefix + TEST_DEVICE_NAME1);
+ Button btn2 =
+ view.findViewHolderForAdapterPosition(1).itemView.findViewById(R.id.device_button);
+ assertThat(btn2.getText().toString()).isEqualTo(prefix + TEST_DEVICE_NAME2);
+ btn1.performClick();
+ assertThat(isItemBtnClicked.get()).isFalse();
+
+ // Update dialog content with same group
+ mFragment.show(mParent, mDeviceItems, mCachedDevice3, (item) -> isItemBtnClicked.set(true));
+ shadowMainLooper().idle();
+ dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog.isShowing()).isTrue();
+ btn1 = view.findViewHolderForAdapterPosition(0).itemView.findViewById(R.id.device_button);
+ btn1.performClick();
+ assertThat(isItemBtnClicked.get()).isTrue();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
+ public void onCreateDialog_dialogIsShowingForNewGroup_updateDialog() {
+ String prefix = "Disconnect ";
+ AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog.isShowing()).isTrue();
+ ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
+ View rootView = shadowDialog.getView();
+ RecyclerView view = rootView.findViewById(R.id.device_btn_list);
+ assertThat(view.getAdapter().getItemCount()).isEqualTo(2);
+
+ // Update dialog content with new group
+ ArrayList<AudioSharingDeviceItem> newDeviceItems = new ArrayList<>();
+ newDeviceItems.add(TEST_DEVICE_ITEM2);
+ newDeviceItems.add(TEST_DEVICE_ITEM3);
+ mFragment.show(mParent, newDeviceItems, mCachedDevice1, (item) -> {});
+ shadowMainLooper().idle();
+ dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog.isShowing()).isTrue();
+ shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
+ rootView = shadowDialog.getView();
+ view = rootView.findViewById(R.id.device_btn_list);
+ assertThat(view.getAdapter().getItemCount()).isEqualTo(2);
+ Button btn1 =
+ view.findViewHolderForAdapterPosition(0).itemView.findViewById(R.id.device_button);
+ assertThat(btn1.getText().toString()).isEqualTo(prefix + TEST_DEVICE_NAME2);
+ Button btn2 =
+ view.findViewHolderForAdapterPosition(1).itemView.findViewById(R.id.device_button);
+ assertThat(btn2.getText().toString()).isEqualTo(prefix + TEST_DEVICE_NAME3);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onCreateDialog_clickCancel_dialogDismiss() {
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog.isShowing()).isTrue();
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
View rootView = shadowDialog.getView();
rootView.findViewById(R.id.cancel_btn).performClick();
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragmentTest.java
index 38f80e0..56951c2 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragmentTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;
import android.bluetooth.BluetoothAdapter;
@@ -27,7 +28,6 @@
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.view.View;
-import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
@@ -37,11 +37,13 @@
import com.android.settings.flags.Flags;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
@@ -67,22 +69,32 @@
private static final String TEST_DEVICE_NAME1 = "test1";
private static final String TEST_DEVICE_NAME2 = "test2";
- private static final AudioSharingDeviceItem TEST_DEVICE_ITEM =
+ private static final AudioSharingDeviceItem TEST_DEVICE_ITEM1 =
new AudioSharingDeviceItem(TEST_DEVICE_NAME1, /* groupId= */ 1, /* isActive= */ true);
+ private static final AudioSharingDeviceItem TEST_DEVICE_ITEM2 =
+ new AudioSharingDeviceItem(TEST_DEVICE_NAME2, /* groupId= */ 2, /* isActive= */ false);
+ @Mock private CachedBluetoothDevice mCachedDevice1;
+ @Mock private CachedBluetoothDevice mCachedDevice2;
private Fragment mParent;
private AudioSharingJoinDialogFragment mFragment;
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
@Before
public void setUp() {
- ShadowAlertDialogCompat.reset();
+ AlertDialog latestAlertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ if (latestAlertDialog != null) {
+ latestAlertDialog.dismiss();
+ ShadowAlertDialogCompat.reset();
+ }
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
mShadowBluetoothAdapter.setEnabled(true);
mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
+ when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
+ when(mCachedDevice2.getName()).thenReturn(TEST_DEVICE_NAME2);
mFragment = new AudioSharingJoinDialogFragment();
mParent = new Fragment();
FragmentController.setupFragment(
@@ -92,7 +104,7 @@
@Test
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onCreateDialog_flagOff_dialogNotExist() {
- mFragment.show(mParent, new ArrayList<>(), TEST_DEVICE_NAME2, () -> {});
+ mFragment.show(mParent, new ArrayList<>(), mCachedDevice2, () -> {});
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNull();
@@ -101,37 +113,58 @@
@Test
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onCreateDialog_flagOn_dialogShowTextForSingleDevice() {
- mFragment.show(mParent, new ArrayList<>(), TEST_DEVICE_NAME2, () -> {});
+ mFragment.show(mParent, new ArrayList<>(), mCachedDevice2, () -> {});
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNotNull();
assertThat(dialog.isShowing()).isTrue();
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
- View rootView = shadowDialog.getView();
- TextView subtitle1 = rootView.findViewById(R.id.share_audio_subtitle1);
- assertThat(subtitle1.getText()).isEqualTo(TEST_DEVICE_NAME2);
+ assertThat(shadowDialog.getMessage().toString()).isEqualTo(TEST_DEVICE_NAME2);
}
@Test
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onCreateDialog_flagOn_dialogShowTextForTwoDevice() {
ArrayList<AudioSharingDeviceItem> list = new ArrayList<>();
- list.add(TEST_DEVICE_ITEM);
- mFragment.show(mParent, list, TEST_DEVICE_NAME2, () -> {});
+ list.add(TEST_DEVICE_ITEM1);
+ mFragment.show(mParent, list, mCachedDevice2, () -> {});
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNotNull();
assertThat(dialog.isShowing()).isTrue();
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
- View rootView = shadowDialog.getView();
- TextView subtitle1 = rootView.findViewById(R.id.share_audio_subtitle1);
- assertThat(subtitle1.getText()).isEqualTo(TEST_DEVICE_NAME1 + " and " + TEST_DEVICE_NAME2);
+ assertThat(shadowDialog.getMessage().toString())
+ .isEqualTo(TEST_DEVICE_NAME1 + " and " + TEST_DEVICE_NAME2);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
+ public void onCreateDialog_dialogIsShowing_updateDialog() {
+ ArrayList<AudioSharingDeviceItem> list = new ArrayList<>();
+ list.add(TEST_DEVICE_ITEM1);
+ mFragment.show(mParent, list, mCachedDevice2, () -> {});
+ shadowMainLooper().idle();
+ AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog).isNotNull();
+ assertThat(dialog.isShowing()).isTrue();
+
+ // Update the content
+ ArrayList<AudioSharingDeviceItem> list2 = new ArrayList<>();
+ list2.add(TEST_DEVICE_ITEM2);
+ mFragment.show(mParent, list2, mCachedDevice1, () -> {});
+ shadowMainLooper().idle();
+ dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog).isNotNull();
+ assertThat(dialog.isShowing()).isTrue();
+ ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
+ assertThat(shadowDialog.getMessage().toString())
+ .isEqualTo(TEST_DEVICE_NAME2 + " and " + TEST_DEVICE_NAME1);
}
@Test
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onCreateDialog_clickCancel_dialogDismiss() {
- mFragment.show(mParent, new ArrayList<>(), TEST_DEVICE_NAME2, () -> {});
+ mFragment.show(mParent, new ArrayList<>(), mCachedDevice2, () -> {});
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
@@ -145,7 +178,7 @@
public void onCreateDialog_clickShare_callbackTriggered() {
AtomicBoolean isShareBtnClicked = new AtomicBoolean(false);
mFragment.show(
- mParent, new ArrayList<>(), TEST_DEVICE_NAME2, () -> isShareBtnClicked.set(true));
+ mParent, new ArrayList<>(), mCachedDevice2, () -> isShareBtnClicked.set(true));
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragmentTest.java
index 61bc88a..d93105d 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragmentTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;
import android.bluetooth.BluetoothAdapter;
@@ -34,11 +35,13 @@
import com.android.settings.flags.Flags;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
@@ -61,21 +64,30 @@
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
- private static final String TEST_DEVICE_NAME = "test";
+ private static final String TEST_DEVICE_NAME1 = "test1";
+ private static final String TEST_DEVICE_NAME2 = "test2";
+ @Mock private CachedBluetoothDevice mCachedDevice1;
+ @Mock private CachedBluetoothDevice mCachedDevice2;
private Fragment mParent;
private AudioSharingStopDialogFragment mFragment;
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
@Before
public void setUp() {
- ShadowAlertDialogCompat.reset();
+ AlertDialog latestAlertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ if (latestAlertDialog != null) {
+ latestAlertDialog.dismiss();
+ ShadowAlertDialogCompat.reset();
+ }
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
mShadowBluetoothAdapter.setEnabled(true);
mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
+ when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
+ when(mCachedDevice2.getName()).thenReturn(TEST_DEVICE_NAME2);
mFragment = new AudioSharingStopDialogFragment();
mParent = new Fragment();
FragmentController.setupFragment(
@@ -85,7 +97,7 @@
@Test
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onCreateDialog_flagOff_dialogNotExist() {
- mFragment.show(mParent, TEST_DEVICE_NAME, () -> {});
+ mFragment.show(mParent, mCachedDevice1, () -> {});
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNull();
@@ -93,8 +105,30 @@
@Test
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
+ public void onCreateDialog_dialogIsShowing_updateDialog() {
+ String postMessage = " wants to connect, headphones in audio sharing will disconnect.";
+ mFragment.show(mParent, mCachedDevice1, () -> {});
+ shadowMainLooper().idle();
+ AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog).isNotNull();
+ assertThat(dialog.isShowing()).isTrue();
+ ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
+ assertThat(shadowDialog.getMessage().toString()).isEqualTo(TEST_DEVICE_NAME1 + postMessage);
+
+ // Update the content
+ mFragment.show(mParent, mCachedDevice2, () -> {});
+ shadowMainLooper().idle();
+ dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog).isNotNull();
+ assertThat(dialog.isShowing()).isTrue();
+ shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
+ assertThat(shadowDialog.getMessage().toString()).isEqualTo(TEST_DEVICE_NAME2 + postMessage);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onCreateDialog_clickCancel_dialogDismiss() {
- mFragment.show(mParent, TEST_DEVICE_NAME, () -> {});
+ mFragment.show(mParent, mCachedDevice1, () -> {});
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
dialog.findViewById(android.R.id.button2).performClick();
@@ -106,7 +140,7 @@
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onCreateDialog_clickShare_callbackTriggered() {
AtomicBoolean isStopBtnClicked = new AtomicBoolean(false);
- mFragment.show(mParent, TEST_DEVICE_NAME, () -> isStopBtnClicked.set(true));
+ mFragment.show(mParent, mCachedDevice1, () -> isStopBtnClicked.set(true));
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
dialog.findViewById(android.R.id.button1).performClick();