Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d2c36148 authored by Yiyi Shen's avatar Yiyi Shen Committed by Android (Google) Code Review
Browse files

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

parents abe0c76c 28ef49e0
Loading
Loading
Loading
Loading
+60 −7
Original line number Diff line number Diff line
@@ -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);
    }
}
+91 −0
Original line number Diff line number Diff line
/*
 * 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;
    }
}