Merge "[Audiosharing] Impl the stop audio sharing dialog." into main

This commit is contained in:
Yiyi Shen
2023-11-13 09:43:46 +00:00
committed by Android (Google) Code Review
2 changed files with 151 additions and 7 deletions

View File

@@ -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.core.BasePreferenceController;
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 @@ 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 PreferenceGroup mPreferenceGroup;
private Preference mAudioSharingSettingsPreference;
private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
private DashboardFragment mFragment;
private BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
new BluetoothLeBroadcastAssistant.Callback() {
@@ -149,6 +158,7 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro
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 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro
@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 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro
@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 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro
}
}
@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);
}
}

View File

@@ -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;
}
}