Loading res/layout/dialog_audio_sharing_join.xml +1 −10 Original line number Diff line number Diff line Loading @@ -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" Loading src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java +83 −14 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -27,6 +28,7 @@ import android.content.Context; 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; Loading @@ -43,6 +45,7 @@ import com.android.settings.dashboard.DashboardFragment; 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; Loading @@ -68,9 +71,10 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro "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; Loading Loading @@ -165,6 +169,12 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro + ", reason = " + reason); mBluetoothDeviceUpdater.forceUpdate(); if (mDeviceManager != null) { CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(sink); if (cachedDevice != null) { closeOpeningDialogsForLeaDevice(cachedDevice); } } } @Override Loading Loading @@ -241,8 +251,11 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro public AudioSharingDevicePreferenceController(Context context) { super(context, KEY); mLocalBtManager = Utils.getLocalBtManager(mContext); if (mLocalBtManager != null) { mDeviceManager = mLocalBtManager.getCachedDeviceManager(); mBroadcast = mLocalBtManager.getProfileManager().getLeAudioBroadcastProfile(); mAssistant = mLocalBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile(); } mExecutor = Executors.newSingleThreadExecutor(); } Loading Loading @@ -344,6 +357,17 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro @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; Loading Loading @@ -420,10 +444,10 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro // connected during a sharing session. postOnMainThread( () -> { closeOpeningDialogs(); closeOpeningDialogsOtherThan(AudioSharingStopDialogFragment.tag()); AudioSharingStopDialogFragment.show( mFragment, cachedDevice.getName(), cachedDevice, () -> mBroadcast.stopBroadcast(mBroadcast.getLatestBroadcastId())); }); } else { Loading Loading @@ -466,11 +490,12 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro 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())) { Loading @@ -497,11 +522,11 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro // 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( Loading @@ -527,11 +552,11 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro if (deviceItems.size() == 1) { postOnMainThread( () -> { closeOpeningDialogs(); closeOpeningDialogsOtherThan(AudioSharingJoinDialogFragment.tag()); AudioSharingJoinDialogFragment.show( mFragment, deviceItems, cachedDevice.getName(), cachedDevice, () -> { mTargetSinks = new ArrayList<>(); for (List<CachedBluetoothDevice> devices : Loading Loading @@ -591,17 +616,61 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro } } 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); } Loading src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragment.java +58 −11 Original line number Diff line number Diff line Loading @@ -19,13 +19,17 @@ package com.android.settings.connecteddevice.audiosharing; 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; Loading @@ -33,8 +37,10 @@ import androidx.recyclerview.widget.RecyclerView; 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"; Loading @@ -56,6 +62,7 @@ public class AudioSharingDisconnectDialogFragment extends InstrumentedDialogFrag } private static DialogEventListener sListener; @Nullable private static CachedBluetoothDevice sNewDevice; @Override public int getMetricsCategory() { Loading @@ -65,35 +72,78 @@ public class AudioSharingDisconnectDialogFragment extends InstrumentedDialogFrag /** * 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); Loading @@ -115,10 +165,7 @@ public class AudioSharingDisconnectDialogFragment extends InstrumentedDialogFrag 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; Loading src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragment.java +74 −25 Original line number Diff line number Diff line Loading @@ -18,19 +18,25 @@ package com.android.settings.connecteddevice.audiosharing; 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; Loading @@ -49,6 +55,7 @@ public class AudioSharingJoinDialogFragment extends InstrumentedDialogFragment { } private static DialogEventListener sListener; private static @Nullable CachedBluetoothDevice sNewDevice; @Override public int getMetricsCategory() { Loading @@ -58,29 +65,54 @@ public class AudioSharingJoinDialogFragment extends InstrumentedDialogFragment { /** * 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; 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, newDeviceName); final AudioSharingJoinDialogFragment dialog = new AudioSharingJoinDialogFragment(); dialog.setArguments(bundle); dialog.show(manager, TAG); 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); Loading @@ -88,6 +120,7 @@ public class AudioSharingJoinDialogFragment extends InstrumentedDialogFragment { 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); Loading @@ -95,21 +128,8 @@ public class AudioSharingJoinDialogFragment extends InstrumentedDialogFragment { 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( Loading @@ -119,8 +139,37 @@ public class AudioSharingJoinDialogFragment extends InstrumentedDialogFragment { }); 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)); } } } src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragment.java +55 −10 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
res/layout/dialog_audio_sharing_join.xml +1 −10 Original line number Diff line number Diff line Loading @@ -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" Loading
src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java +83 −14 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -27,6 +28,7 @@ import android.content.Context; 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; Loading @@ -43,6 +45,7 @@ import com.android.settings.dashboard.DashboardFragment; 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; Loading @@ -68,9 +71,10 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro "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; Loading Loading @@ -165,6 +169,12 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro + ", reason = " + reason); mBluetoothDeviceUpdater.forceUpdate(); if (mDeviceManager != null) { CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(sink); if (cachedDevice != null) { closeOpeningDialogsForLeaDevice(cachedDevice); } } } @Override Loading Loading @@ -241,8 +251,11 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro public AudioSharingDevicePreferenceController(Context context) { super(context, KEY); mLocalBtManager = Utils.getLocalBtManager(mContext); if (mLocalBtManager != null) { mDeviceManager = mLocalBtManager.getCachedDeviceManager(); mBroadcast = mLocalBtManager.getProfileManager().getLeAudioBroadcastProfile(); mAssistant = mLocalBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile(); } mExecutor = Executors.newSingleThreadExecutor(); } Loading Loading @@ -344,6 +357,17 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro @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; Loading Loading @@ -420,10 +444,10 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro // connected during a sharing session. postOnMainThread( () -> { closeOpeningDialogs(); closeOpeningDialogsOtherThan(AudioSharingStopDialogFragment.tag()); AudioSharingStopDialogFragment.show( mFragment, cachedDevice.getName(), cachedDevice, () -> mBroadcast.stopBroadcast(mBroadcast.getLatestBroadcastId())); }); } else { Loading Loading @@ -466,11 +490,12 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro 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())) { Loading @@ -497,11 +522,11 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro // 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( Loading @@ -527,11 +552,11 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro if (deviceItems.size() == 1) { postOnMainThread( () -> { closeOpeningDialogs(); closeOpeningDialogsOtherThan(AudioSharingJoinDialogFragment.tag()); AudioSharingJoinDialogFragment.show( mFragment, deviceItems, cachedDevice.getName(), cachedDevice, () -> { mTargetSinks = new ArrayList<>(); for (List<CachedBluetoothDevice> devices : Loading Loading @@ -591,17 +616,61 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro } } 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); } Loading
src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragment.java +58 −11 Original line number Diff line number Diff line Loading @@ -19,13 +19,17 @@ package com.android.settings.connecteddevice.audiosharing; 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; Loading @@ -33,8 +37,10 @@ import androidx.recyclerview.widget.RecyclerView; 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"; Loading @@ -56,6 +62,7 @@ public class AudioSharingDisconnectDialogFragment extends InstrumentedDialogFrag } private static DialogEventListener sListener; @Nullable private static CachedBluetoothDevice sNewDevice; @Override public int getMetricsCategory() { Loading @@ -65,35 +72,78 @@ public class AudioSharingDisconnectDialogFragment extends InstrumentedDialogFrag /** * 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); Loading @@ -115,10 +165,7 @@ public class AudioSharingDisconnectDialogFragment extends InstrumentedDialogFrag 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; Loading
src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragment.java +74 −25 Original line number Diff line number Diff line Loading @@ -18,19 +18,25 @@ package com.android.settings.connecteddevice.audiosharing; 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; Loading @@ -49,6 +55,7 @@ public class AudioSharingJoinDialogFragment extends InstrumentedDialogFragment { } private static DialogEventListener sListener; private static @Nullable CachedBluetoothDevice sNewDevice; @Override public int getMetricsCategory() { Loading @@ -58,29 +65,54 @@ public class AudioSharingJoinDialogFragment extends InstrumentedDialogFragment { /** * 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; 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, newDeviceName); final AudioSharingJoinDialogFragment dialog = new AudioSharingJoinDialogFragment(); dialog.setArguments(bundle); dialog.show(manager, TAG); 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); Loading @@ -88,6 +120,7 @@ public class AudioSharingJoinDialogFragment extends InstrumentedDialogFragment { 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); Loading @@ -95,21 +128,8 @@ public class AudioSharingJoinDialogFragment extends InstrumentedDialogFragment { 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( Loading @@ -119,8 +139,37 @@ public class AudioSharingJoinDialogFragment extends InstrumentedDialogFragment { }); 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)); } } }
src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragment.java +55 −10 File changed.Preview size limit exceeded, changes collapsed. Show changes