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

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

Merge "[Audiosharing] Impl active device switch for calls and alarms" into main

parents 4a88ae49 d1f0efc2
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -22,10 +22,12 @@ import android.os.Parcelable;
public final class AudioSharingDeviceItem implements Parcelable {
    private final String mName;
    private final int mGroupId;
    private final boolean mIsActive;

    public AudioSharingDeviceItem(String name, int groupId) {
    public AudioSharingDeviceItem(String name, int groupId, boolean isActive) {
        mName = name;
        mGroupId = groupId;
        mIsActive = isActive;
    }

    public String getName() {
@@ -36,15 +38,21 @@ public final class AudioSharingDeviceItem implements Parcelable {
        return mGroupId;
    }

    public boolean isActive() {
        return mIsActive;
    }

    public AudioSharingDeviceItem(Parcel in) {
        mName = in.readString();
        mGroupId = in.readInt();
        mIsActive = in.readBoolean();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mName);
        dest.writeInt(mGroupId);
        dest.writeBoolean(mIsActive);
    }

    @Override
+4 −1
Original line number Diff line number Diff line
@@ -120,6 +120,9 @@ public class AudioSharingUtils {
    /** Build {@link AudioSharingDeviceItem} from {@link CachedBluetoothDevice}. */
    public static AudioSharingDeviceItem buildAudioSharingDeviceItem(
            CachedBluetoothDevice cachedDevice) {
        return new AudioSharingDeviceItem(cachedDevice.getName(), cachedDevice.getGroupId());
        return new AudioSharingDeviceItem(
                cachedDevice.getName(),
                cachedDevice.getGroupId(),
                BluetoothUtils.isActiveLeAudioDevice(cachedDevice));
    }
}
+36 −5
Original line number Diff line number Diff line
@@ -28,9 +28,25 @@ import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.flags.Flags;

import java.util.ArrayList;

/** Provides a dialog to choose the active device for calls and alarms. */
public class CallsAndAlarmsDialogFragment extends InstrumentedDialogFragment {
    private static final String TAG = "CallsAndAlarmsDialog";
    private static final String BUNDLE_KEY_DEVICE_ITEMS = "bundle_key_device_items";

    // 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 device item to set active for calls and alarms in the dialog.
         *
         * @param item The device item clicked.
         */
        void onItemClick(AudioSharingDeviceItem item);
    }

    private static DialogEventListener sListener;

    @Override
    public int getMetricsCategory() {
@@ -41,28 +57,43 @@ public class CallsAndAlarmsDialogFragment extends InstrumentedDialogFragment {
     * Display the {@link CallsAndAlarmsDialogFragment} dialog.
     *
     * @param host The Fragment this dialog will be hosted.
     * @param deviceItems The connected device items in audio sharing session.
     * @param listener The callback to handle the user action on this dialog.
     */
    public static void show(Fragment host) {
    public static void show(
            Fragment host,
            ArrayList<AudioSharingDeviceItem> deviceItems,
            DialogEventListener listener) {
        if (!Flags.enableLeAudioSharing()) return;
        final FragmentManager manager = host.getChildFragmentManager();
        sListener = listener;
        if (manager.findFragmentByTag(TAG) == null) {
            final Bundle bundle = new Bundle();
            bundle.putParcelableArrayList(BUNDLE_KEY_DEVICE_ITEMS, deviceItems);
            final CallsAndAlarmsDialogFragment dialog = new CallsAndAlarmsDialogFragment();
            dialog.setArguments(bundle);
            dialog.show(manager, TAG);
        }
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // TODO: use real device names
        String[] choices = {"Buds 1", "Buds 2"};
        Bundle arguments = requireArguments();
        ArrayList<AudioSharingDeviceItem> deviceItems =
                arguments.getParcelableArrayList(BUNDLE_KEY_DEVICE_ITEMS);
        int checkedItem = -1;
        // deviceItems is ordered. The active device is put in the first place if it does exist
        if (!deviceItems.isEmpty() && deviceItems.get(0).isActive()) checkedItem = 0;
        String[] choices =
                deviceItems.stream().map(AudioSharingDeviceItem::getName).toArray(String[]::new);
        AlertDialog.Builder builder =
                new AlertDialog.Builder(getActivity())
                        .setTitle(R.string.calls_and_alarms_device_title)
                        .setSingleChoiceItems(
                                choices,
                                0, // TODO: set to current active device.
                                checkedItem,
                                (dialog, which) -> {
                                    // TODO: set device to active device for calls and alarms.
                                    sListener.onItemClick(deviceItems.get(which));
                                });
        return builder.create();
    }
+75 −5
Original line number Diff line number Diff line
@@ -16,23 +16,42 @@

package com.android.settings.connecteddevice.audiosharing;

import android.annotation.Nullable;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.PreferenceScreen;

import com.android.settings.bluetooth.Utils;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/** PreferenceController to control the dialog to choose the active device for calls and alarms */
public class CallsAndAlarmsPreferenceController extends AudioSharingBasePreferenceController {
public class CallsAndAlarmsPreferenceController extends AudioSharingBasePreferenceController
        implements BluetoothCallback, DefaultLifecycleObserver {

    private static final String TAG = "CallsAndAlarmsPreferenceController";

    private static final String PREF_KEY = "calls_and_alarms";

    private final LocalBluetoothManager mLocalBtManager;
    private DashboardFragment mFragment;
    Map<Integer, List<CachedBluetoothDevice>> mGroupedConnectedDevices = new HashMap<>();
    private ArrayList<AudioSharingDeviceItem> mDeviceItemsInSharingSession = new ArrayList<>();

    public CallsAndAlarmsPreferenceController(Context context) {
        super(context, PREF_KEY);
        mLocalBtManager = Utils.getLocalBtManager(mContext);
    }

    @Override
@@ -43,17 +62,60 @@ public class CallsAndAlarmsPreferenceController extends AudioSharingBasePreferen
    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        updateDeviceItemsInSharingSession();
        // mDeviceItemsInSharingSession is ordered. The active device is the first place if exits.
        if (!mDeviceItemsInSharingSession.isEmpty()
                && mDeviceItemsInSharingSession.get(0).isActive()) {
            mPreference.setSummary(mDeviceItemsInSharingSession.get(0).getName());
        } else {
            mPreference.setSummary("");
        }
        mPreference.setOnPreferenceClickListener(
                preference -> {
                    if (mFragment != null) {
                        CallsAndAlarmsDialogFragment.show(mFragment);
                    } else {
                    if (mFragment == null) {
                        Log.w(TAG, "Dialog fail to show due to null host.");
                        return true;
                    }
                    updateDeviceItemsInSharingSession();
                    if (mDeviceItemsInSharingSession.size() >= 2) {
                        CallsAndAlarmsDialogFragment.show(
                                mFragment,
                                mDeviceItemsInSharingSession,
                                (AudioSharingDeviceItem item) -> {
                                    for (CachedBluetoothDevice device :
                                            mGroupedConnectedDevices.get(item.getGroupId())) {
                                        device.setActive();
                                    }
                                });
                    }
                    return true;
                });
    }

    @Override
    public void onStart(@NonNull LifecycleOwner owner) {
        if (mLocalBtManager != null) {
            mLocalBtManager.getEventManager().registerCallback(this);
        }
    }

    @Override
    public void onStop(@NonNull LifecycleOwner owner) {
        if (mLocalBtManager != null) {
            mLocalBtManager.getEventManager().unregisterCallback(this);
        }
    }

    @Override
    public void onActiveDeviceChanged(
            @Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) {
        if (bluetoothProfile != BluetoothProfile.LE_AUDIO) {
            Log.d(TAG, "Ignore onActiveDeviceChanged, not LE_AUDIO profile");
            return;
        }
        mPreference.setSummary(activeDevice == null ? "" : activeDevice.getName());
    }

    /**
     * Initialize the controller.
     *
@@ -62,4 +124,12 @@ public class CallsAndAlarmsPreferenceController extends AudioSharingBasePreferen
    public void init(DashboardFragment fragment) {
        this.mFragment = fragment;
    }

    private void updateDeviceItemsInSharingSession() {
        mGroupedConnectedDevices =
                AudioSharingUtils.fetchConnectedDevicesByGroupId(mLocalBtManager);
        mDeviceItemsInSharingSession =
                AudioSharingUtils.buildOrderedDeviceItemsInSharingSession(
                        mGroupedConnectedDevices, mLocalBtManager);
    }
}