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

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

Merge "[Audiosharing] Update the dialog content in place" into main

parents dc5ed1f3 a55759ef
Loading
Loading
Loading
Loading
+19 −1
Original line number Diff line number Diff line
@@ -28,6 +28,9 @@ import androidx.recyclerview.widget.RecyclerView;

import com.android.settings.R;

import com.google.common.collect.ImmutableList;

import java.util.ArrayList;
import java.util.List;

public class AudioSharingDeviceAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@@ -35,7 +38,7 @@ public class AudioSharingDeviceAdapter extends RecyclerView.Adapter<RecyclerView
    private static final String TAG = "AudioSharingDeviceAdapter";

    private final Context mContext;
    private final List<AudioSharingDeviceItem> mDevices;
    private List<AudioSharingDeviceItem> mDevices;
    private final OnClickListener mOnClickListener;
    private final ActionType mType;

@@ -113,6 +116,21 @@ public class AudioSharingDeviceAdapter extends RecyclerView.Adapter<RecyclerView
        return mDevices.size();
    }

    /** Updates the data set and notify the change. */
    public void updateItems(@NonNull List<AudioSharingDeviceItem> items) {
        if (mDevices.size() != items.size()) {
            List<AudioSharingDeviceItem> oldItems = new ArrayList<>(mDevices);
            oldItems.removeAll(items);
            if (oldItems.isEmpty()) {
                Log.d(TAG, "Skip updateItems, no change");
                return;
            }
        }
        mDevices = ImmutableList.copyOf(items);
        Log.d(TAG, "updateItems, items = " + mDevices);
        notifyDataSetChanged();
    }

    public interface OnClickListener {
        /** Called when an item has been clicked. */
        void onClick(AudioSharingDeviceItem item);
+15 −0
Original line number Diff line number Diff line
@@ -20,6 +20,9 @@ import android.os.Parcel;
import android.os.Parcelable;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.Objects;

public final class AudioSharingDeviceItem implements Parcelable {
    private final String mName;
@@ -80,4 +83,16 @@ public final class AudioSharingDeviceItem implements Parcelable {
    public String toString() {
        return "AudioSharingDeviceItem groupId = " + mGroupId + ", isActive = " + mIsActive;
    }

    @Override
    public boolean equals(@Nullable Object obj) {
        if (!(obj instanceof AudioSharingDeviceItem other)) return false;
        return mName.equals(other.getName()) && mGroupId == other.getGroupId()
                && mIsActive == other.isActive();
    }

    @Override
    public int hashCode() {
        return Objects.hash(mName, mGroupId, mIsActive);
    }
}
+49 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ import androidx.recyclerview.widget.RecyclerView;

import com.android.settings.R;

import java.util.List;

import javax.annotation.CheckReturnValue;

public class AudioSharingDialogFactory {
@@ -50,6 +52,53 @@ public class AudioSharingDialogFactory {
        return new AudioSharingDialogFactory.DialogBuilder(context);
    }

    /**
     * Updates the title of the dialog custom title.
     *
     * @param dialog    The dialog to update
     * @param titleText The text to be used for the title..
     */
    public static void updateTitle(@NonNull AlertDialog dialog,
            @NonNull CharSequence titleText) {
        TextView title = dialog.findViewById(R.id.title_text);
        if (title != null) {
            title.setText(titleText);
            title.setVisibility(View.VISIBLE);
        }
    }

    /**
     * Updates the custom message of the dialog custom body.
     *
     * @param dialog  The dialog to update
     * @param message The text to be used for the custom message body.
     */
    public static void updateCustomMessage(@NonNull AlertDialog dialog,
            @NonNull CharSequence message) {
        TextView subTitle = dialog.findViewById(R.id.description_text);
        if (subTitle != null) {
            subTitle.setText(message);
            subTitle.setVisibility(View.VISIBLE);
        }
    }

    /**
     * Updates the custom device actions of the dialog custom body.
     *
     * @param dialog      The dialog to update
     * @param deviceItems device items to build dialog actions.
     */
    public static void updateCustomDeviceActions(
            @NonNull AlertDialog dialog, @NonNull List<AudioSharingDeviceItem> deviceItems) {
        RecyclerView recyclerView = dialog.findViewById(R.id.device_btn_list);
        if (recyclerView != null && recyclerView.getVisibility() == View.VISIBLE) {
            RecyclerView.Adapter adapter = recyclerView.getAdapter();
            if (adapter instanceof AudioSharingDeviceAdapter) {
                ((AudioSharingDeviceAdapter) adapter).updateItems(deviceItems);
            }
        }
    }

    /** Builder class with configurable options for the dialog to be shown for audio sharing. */
    public static class DialogBuilder {
        private Context mContext;
+47 −68
Original line number Diff line number Diff line
@@ -33,21 +33,19 @@ import androidx.lifecycle.Lifecycle;

import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.flags.Flags;
import com.android.settingslib.utils.ThreadUtils;

import com.google.common.collect.ImmutableList;

import java.util.List;
import java.util.Locale;

public class AudioSharingDisconnectDialogFragment extends InstrumentedDialogFragment {
    private static final String TAG = "AudioSharingDisconnectDialog";

    private static final String BUNDLE_KEY_DEVICE_TO_DISCONNECT_ITEMS =
            "bundle_key_device_to_disconnect_items";
    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.
@@ -80,8 +78,10 @@ public class AudioSharingDisconnectDialogFragment extends InstrumentedDialogFrag
     * @param newDevice The latest connected device triggered this dialog.
     * @param listener The callback to handle the user action on this dialog.
     * @param eventData The eventData to log with for dialog onClick events.
     *
     * @return whether the dialog is shown
     */
    public static void show(
    public static boolean show(
            @Nullable Fragment host,
            @NonNull List<AudioSharingDeviceItem> deviceItems,
            @NonNull CachedBluetoothDevice newDevice,
@@ -89,60 +89,46 @@ public class AudioSharingDisconnectDialogFragment extends InstrumentedDialogFrag
            @NonNull Pair<Integer, Object>[] eventData) {
        if (host == null) {
            Log.d(TAG, "Fail to show dialog, host is null");
            return;
            return false;
        }
        if (!BluetoothUtils.isAudioSharingUIAvailable(host.getContext())) {
            Log.d(TAG, "Fail to show dialog, feature disabled");
            return false;
        }
        if (BluetoothUtils.isAudioSharingUIAvailable(host.getContext())) {
        final FragmentManager manager;
        try {
            manager = host.getChildFragmentManager();
        } catch (IllegalStateException e) {
            Log.d(TAG, "Fail to show dialog: " + e.getMessage());
                return;
            return false;
        }
        Lifecycle.State currentState = host.getLifecycle().getCurrentState();
        if (!currentState.isAtLeast(Lifecycle.State.STARTED)) {
            Log.d(TAG, "Fail to show dialog with state: " + currentState);
                return;
            return false;
        }
            AlertDialog dialog = AudioSharingDialogHelper.getDialogIfShowing(manager, TAG);
            if (dialog != null) {
                int newGroupId = BluetoothUtils.getGroupId(newDevice);
                if (sNewDevice != null && newGroupId == BluetoothUtils.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;
        sEventData = eventData;
                    return;
        AudioSharingUtils.postOnMainThread(
                host.getContext(),
                () -> {
                    AlertDialog dialog = AudioSharingDialogHelper.getDialogIfShowing(manager, TAG);
                    if (dialog != null) {
                        Log.d(TAG, "Dialog is showing, update the content.");
                        updateDialog(ImmutableList.copyOf(deviceItems), dialog);
                    } else {
                    Log.d(
                            TAG,
                            String.format(
                                    Locale.US,
                                    "Dialog is showing for new device group %d, "
                                            + "dismiss current dialog.",
                                    newGroupId));
                    dialog.dismiss();
                    logDialogAutoDismiss(dialog);
                }
            }
            sListener = listener;
            sNewDevice = newDevice;
            sEventData = eventData;
                        Log.d(TAG, "Show up the dialog.");
                        final Bundle bundle = new Bundle();
            bundle.putParcelableList(BUNDLE_KEY_DEVICE_TO_DISCONNECT_ITEMS, deviceItems);
            bundle.putString(BUNDLE_KEY_NEW_DEVICE_NAME, newDevice.getName());
                        bundle.putParcelableList(BUNDLE_KEY_DEVICE_TO_DISCONNECT_ITEMS,
                                deviceItems);
                        AudioSharingDisconnectDialogFragment dialogFrag =
                                new AudioSharingDisconnectDialogFragment();
                        dialogFrag.setArguments(bundle);
                        dialogFrag.show(manager, TAG);
                    }
                });
        return true;
    }

    /** Return the tag of {@link AudioSharingDisconnectDialogFragment} dialog. */
@@ -226,16 +212,9 @@ public class AudioSharingDisconnectDialogFragment extends InstrumentedDialogFrag
        }
    }

    private static void logDialogAutoDismiss(AlertDialog dialog) {
        var unused =
                ThreadUtils.postOnBackgroundThread(
                        () -> FeatureFactory.getFeatureFactory()
                                .getMetricsFeatureProvider()
                                .action(
                                        dialog.getContext(),
                                        SettingsEnums
                                                .ACTION_AUDIO_SHARING_DIALOG_AUTO_DISMISS,
                                        SettingsEnums
                                                .DIALOG_AUDIO_SHARING_SWITCH_DEVICE));
    private static void updateDialog(
            @NonNull List<AudioSharingDeviceItem> deviceItems,
            @NonNull AlertDialog dialog) {
        AudioSharingDialogFactory.updateCustomDeviceActions(dialog, deviceItems);
    }
}
+42 −32
Original line number Diff line number Diff line
@@ -77,8 +77,10 @@ public class AudioSharingJoinDialogFragment extends InstrumentedDialogFragment {
     * @param newDevice The latest connected device triggered this dialog.
     * @param listener The callback to handle the user action on this dialog.
     * @param eventData The eventData to log with for dialog onClick events.
     *
     * @return whether the dialog is shown
     */
    public static void show(
    public static boolean show(
            @Nullable Fragment host,
            @NonNull List<AudioSharingDeviceItem> deviceItems,
            @NonNull CachedBluetoothDevice newDevice,
@@ -86,25 +88,32 @@ public class AudioSharingJoinDialogFragment extends InstrumentedDialogFragment {
            @NonNull Pair<Integer, Object>[] eventData) {
        if (host == null) {
            Log.d(TAG, "Fail to show dialog, host is null");
            return;
            return false;
        }
        if (!BluetoothUtils.isAudioSharingUIAvailable(host.getContext())) {
            Log.d(TAG, "Fail to show dialog, feature disabled");
            return false;
        }
        if (BluetoothUtils.isAudioSharingUIAvailable(host.getContext())) {
        final FragmentManager manager;
        try {
            manager = host.getChildFragmentManager();
        } catch (IllegalStateException e) {
            Log.d(TAG, "Fail to show dialog: " + e.getMessage());
                return;
            return false;
        }
        Lifecycle.State currentState = host.getLifecycle().getCurrentState();
        if (!currentState.isAtLeast(Lifecycle.State.STARTED)) {
            Log.d(TAG, "Fail to show dialog with state: " + currentState);
                return;
            return false;
        }
        sListener = listener;
        sNewDevice = newDevice;
        sEventData = eventData;
            AlertDialog dialog = AudioSharingDialogHelper.getDialogIfShowing(manager, TAG);
        AudioSharingUtils.postOnMainThread(
                host.getContext(),
                () -> {
                    AlertDialog dialog = AudioSharingDialogHelper.getDialogIfShowing(manager,
                            TAG);
                    if (dialog != null) {
                        Log.d(TAG, "Dialog is showing, update the content.");
                        updateDialog(deviceItems, newDevice.getName(), dialog);
@@ -118,7 +127,8 @@ public class AudioSharingJoinDialogFragment extends InstrumentedDialogFragment {
                        dialogFrag.setArguments(bundle);
                        dialogFrag.show(manager, TAG);
                    }
        }
                });
        return true;
    }

    /** Return the tag of {@link AudioSharingJoinDialogFragment} dialog. */
Loading