Merge "[Audiosharing] Impl the stop audio sharing dialog." into main
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
index d4803c6..0a6795f 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
@@ -16,10 +16,12 @@
package com.android.settings.connecteddevice.audiosharing;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastAssistant;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.pm.PackageManager;
import android.util.Log;
@@ -38,9 +40,14 @@
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.flags.Flags;
import com.android.settingslib.bluetooth.BluetoothCallback;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LeAudioProfile;
+import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfile;
+import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -53,11 +60,13 @@
"connected_device_audio_sharing_settings";
private final LocalBluetoothManager mLocalBtManager;
+ private final LocalBluetoothLeBroadcast mBroadcast;
private final LocalBluetoothLeBroadcastAssistant mAssistant;
private final Executor mExecutor;
private PreferenceGroup mPreferenceGroup;
private Preference mAudioSharingSettingsPreference;
private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
+ private DashboardFragment mFragment;
private BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
new BluetoothLeBroadcastAssistant.Callback() {
@@ -149,6 +158,7 @@
public AudioSharingDevicePreferenceController(Context context) {
super(context, KEY);
mLocalBtManager = Utils.getLocalBtManager(mContext);
+ mBroadcast = mLocalBtManager.getProfileManager().getLeAudioBroadcastProfile();
mAssistant = mLocalBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile();
mExecutor = Executors.newSingleThreadExecutor();
}
@@ -156,15 +166,15 @@
@Override
public void onStart(@NonNull LifecycleOwner owner) {
if (mLocalBtManager == null) {
- Log.e(TAG, "onStart() Bluetooth is not supported on this device");
+ Log.d(TAG, "onStart() Bluetooth is not supported on this device");
return;
}
if (mAssistant == null) {
- Log.e(TAG, "onStart() Broadcast assistant is not supported on this device");
+ Log.d(TAG, "onStart() Broadcast assistant is not supported on this device");
return;
}
if (mBluetoothDeviceUpdater == null) {
- Log.e(TAG, "onStart() Bluetooth device updater is not initialized");
+ Log.d(TAG, "onStart() Bluetooth device updater is not initialized");
return;
}
mLocalBtManager.getEventManager().registerCallback(this);
@@ -176,15 +186,15 @@
@Override
public void onStop(@NonNull LifecycleOwner owner) {
if (mLocalBtManager == null) {
- Log.e(TAG, "onStop() Bluetooth is not supported on this device");
+ Log.d(TAG, "onStop() Bluetooth is not supported on this device");
return;
}
if (mAssistant == null) {
- Log.e(TAG, "onStop() Broadcast assistant is not supported on this device");
+ Log.d(TAG, "onStop() Broadcast assistant is not supported on this device");
return;
}
if (mBluetoothDeviceUpdater == null) {
- Log.e(TAG, "onStop() Bluetooth device updater is not initialized");
+ Log.d(TAG, "onStop() Bluetooth device updater is not initialized");
return;
}
mLocalBtManager.getEventManager().unregisterCallback(this);
@@ -244,17 +254,60 @@
}
}
+ @Override
+ public void onProfileConnectionStateChanged(
+ @NonNull CachedBluetoothDevice cachedDevice,
+ @ConnectionState int state,
+ int bluetoothProfile) {
+ if (state != BluetoothAdapter.STATE_CONNECTED || !cachedDevice.getDevice().isConnected()) {
+ Log.d(TAG, "Ignore onProfileConnectionStateChanged, not connected state");
+ return;
+ }
+ List<LocalBluetoothProfile> supportedProfiles = cachedDevice.getProfiles();
+ boolean isLeAudioSupported = false;
+ for (LocalBluetoothProfile profile : supportedProfiles) {
+ if (profile instanceof LeAudioProfile && profile.isEnabled(cachedDevice.getDevice())) {
+ isLeAudioSupported = true;
+ }
+ if (profile.getProfileId() != bluetoothProfile
+ && profile.getConnectionStatus(cachedDevice.getDevice())
+ == BluetoothProfile.STATE_CONNECTED) {
+ Log.d(
+ TAG,
+ "Ignore onProfileConnectionStateChanged, not the first connected profile");
+ return;
+ }
+ }
+ // Show stop audio sharing dialog when an ineligible (not le audio) remote device connected
+ // during a sharing session.
+ if (isBroadcasting() && !isLeAudioSupported) {
+ if (mFragment != null) {
+ AudioSharingStopDialogFragment.show(
+ mFragment,
+ cachedDevice.getName(),
+ () -> {
+ mBroadcast.stopBroadcast(mBroadcast.getLatestBroadcastId());
+ });
+ }
+ }
+ }
+
/**
* Initialize the controller.
*
* @param fragment The fragment to provide the context and metrics category for {@link
- * AudioSharingBluetoothDeviceUpdater}.
+ * AudioSharingBluetoothDeviceUpdater} and provide the host for dialogs.
*/
public void init(DashboardFragment fragment) {
+ mFragment = fragment;
mBluetoothDeviceUpdater =
new AudioSharingBluetoothDeviceUpdater(
fragment.getContext(),
AudioSharingDevicePreferenceController.this,
fragment.getMetricsCategory());
}
+
+ private boolean isBroadcasting() {
+ return mBroadcast != null && mBroadcast.isEnabled(null);
+ }
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragment.java
new file mode 100644
index 0000000..495fad3
--- /dev/null
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingStopDialogFragment.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.connecteddevice.audiosharing;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.os.Bundle;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.flags.Flags;
+
+public class AudioSharingStopDialogFragment extends InstrumentedDialogFragment {
+ private static final String TAG = "AudioSharingStopDialog";
+
+ private static final String BUNDLE_KEY_NEW_DEVICE_NAME = "bundle_key_new_device_name";
+
+ // The host creates an instance of this dialog fragment must implement this interface to receive
+ // event callbacks.
+ public interface DialogEventListener {
+ /** Called when users click the stop sharing button in the dialog. */
+ void onStopSharingClick();
+ }
+
+ private static DialogEventListener sListener;
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.DIALOG_STOP_AUDIO_SHARING;
+ }
+
+ /**
+ * Display the {@link AudioSharingStopDialogFragment} dialog.
+ *
+ * @param host The Fragment this dialog will be hosted.
+ */
+ public static void show(Fragment host, String newDeviceName, DialogEventListener listener) {
+ if (!Flags.enableLeAudioSharing()) return;
+ final FragmentManager manager = host.getChildFragmentManager();
+ sListener = listener;
+ if (manager.findFragmentByTag(TAG) == null) {
+ final Bundle bundle = new Bundle();
+ bundle.putString(BUNDLE_KEY_NEW_DEVICE_NAME, newDeviceName);
+ AudioSharingStopDialogFragment dialog = new AudioSharingStopDialogFragment();
+ dialog.setArguments(bundle);
+ dialog.show(manager, TAG);
+ }
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ Bundle arguments = requireArguments();
+ String newDeviceName = arguments.getString(BUNDLE_KEY_NEW_DEVICE_NAME);
+ final AlertDialog.Builder builder =
+ new AlertDialog.Builder(getActivity())
+ .setTitle("Stop sharing audio?")
+ .setCancelable(false);
+ builder.setMessage(
+ newDeviceName + " is connected, devices in audio sharing will disconnect.");
+ builder.setPositiveButton(
+ "Stop sharing",
+ (dialog, which) -> {
+ sListener.onStopSharingClick();
+ });
+ builder.setNegativeButton(
+ "Cancel",
+ (dialog, which) -> {
+ dismiss();
+ });
+ AlertDialog dialog = builder.create();
+ dialog.setCanceledOnTouchOutside(false);
+ return dialog;
+ }
+}