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

Commit 2aade0e4 authored by Alexandr Shabalin's avatar Alexandr Shabalin Committed by Android (Google) Code Review
Browse files

Merge changes I14a0753c,I1000adc3 into main

* changes:
  Consolidate the loading indicator and item background rendering.
  Consolidate the end area rendering logic.
parents 225b4dc7 0d977866
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -246,6 +246,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
        assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
        assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
        assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(mViewHolder.mEndClickIcon.getVisibility()).isEqualTo(View.GONE);
        assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(mViewHolder.mEndTouchArea.getVisibility()).isEqualTo(View.VISIBLE);
    }
@@ -297,6 +298,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
        assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
        assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(mViewHolder.mEndTouchArea.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(mViewHolder.mEndClickIcon.getVisibility()).isEqualTo(View.VISIBLE);
    }

    @Test
@@ -312,12 +314,12 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
        assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_1);
        assertThat(mViewHolder.mStatusIcon.getVisibility()).isEqualTo(View.GONE);
        assertThat(mViewHolder.mEndClickIcon.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
        assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
        assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
        assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(mViewHolder.mEndTouchArea.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(mViewHolder.mEndClickIcon.getVisibility()).isEqualTo(View.VISIBLE);
    }

    @Test
@@ -383,7 +385,9 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
        mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);

        assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
        assertThat(mViewHolder.mEndTouchArea.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(mViewHolder.mEndClickIcon.getVisibility()).isEqualTo(View.GONE);
        assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_2);
        assertThat(mViewHolder.mContainerLayout.isFocusable()).isTrue();
+1 −1
Original line number Diff line number Diff line
@@ -17,6 +17,6 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <corners
        android:radius="16dp"/>
        android:radius="@dimen/media_output_dialog_background_radius"/>
    <solid android:color="@color/media_dialog_item_background" />
</shape>
 No newline at end of file
+109 −77
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.widget.TextView;

import androidx.annotation.DoNotInline;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.widget.CompoundButtonCompat;
import androidx.recyclerview.widget.RecyclerView;
@@ -184,6 +185,11 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
                                + "]");
            }

            boolean isDeviceGroup = false;
            GroupStatus groupStatus = null;
            OngoingSessionStatus ongoingSessionStatus = null;
            ConnectionState connectionState = ConnectionState.DISCONNECTED;

            if (mCurrentActivePosition == position) {
                mCurrentActivePosition = -1;
            }
@@ -194,11 +200,9 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
            if (mController.isAnyDeviceTransferring()) {
                if (device.getState() == MediaDeviceState.STATE_CONNECTING
                        && !mController.hasAdjustVolumeUserRestriction()) {
                    connectionState = ConnectionState.CONNECTING;
                    setUpDeviceIcon(device);
                    updateProgressBarColor();
                    setSingleLineLayout(device.getName(), false /* showSeekBar*/,
                            true /* showProgressBar */, false /* showCheckBox */,
                            false /* showEndTouchArea */);
                    setSingleLineLayout(device.getName(), false /* showSeekBar*/);
                } else {
                    setUpDeviceIcon(device);
                    setSingleLineLayout(device.getName());
@@ -207,6 +211,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
                // Set different layout for each device
                if (device.isMutingExpectedDevice()
                        && !mController.isCurrentConnectedDeviceRemote()) {
                    connectionState = ConnectionState.CONNECTED;
                    updateUnmutedVolumeIcon(device);
                    mCurrentActivePosition = position;
                    updateFullItemClickListener(v -> onItemClick(v, device));
@@ -217,47 +222,37 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
                        && isDeviceIncluded(mController.getSelectedMediaDevice(), device)) {
                    if (!mediaItem.isFirstDeviceInGroup()) {
                        mItemLayout.setVisibility(View.GONE);
                        mEndTouchArea.setVisibility(View.GONE);
                        return;
                    } else {
                        isDeviceGroup = true;
                        String sessionName = mController.getSessionName().toString();
                        updateUnmutedVolumeIcon(null);
                        updateEndClickAreaWithIcon(
                                v -> {
                                    mShouldGroupSelectedMediaItems = false;
                                    notifyDataSetChanged();
                                },
                                R.drawable.media_output_item_expand_group,
                                R.string.accessibility_expand_group);
                        disableFocusPropertyForView(mContainerLayout);
                        setUpContentDescriptionForView(mSeekBar, mContext.getString(
                                R.string.accessibility_cast_name, sessionName));
                        setSingleLineLayout(sessionName, true /* showSeekBar */,
                                false /* showProgressBar */, false /* showCheckBox */,
                                true /* showEndTouchArea */);
                        setSingleLineLayout(sessionName, true /* showSeekBar */);
                        initGroupSeekbar(isCurrentSeekbarInvisible);
                    }
                } else if (device.hasSubtext()) {
                    boolean isActiveWithOngoingSession =
                            device.hasOngoingSession() && (currentlyConnected || isSelected);
                    boolean isHost = device.isHostForOngoingSession()
                            && isActiveWithOngoingSession;
                    if (isActiveWithOngoingSession) {
                        mCurrentActivePosition = position;
                        updateUnmutedVolumeIcon(device);
                        mSubTitleText.setText(device.getSubtextString());
                        updateContentAlpha(DEVICE_CONNECTED_ALPHA);
                        updateEndClickAreaAsSessionEditing(device,
                                isHost ? R.drawable.media_output_status_edit_session
                                        : R.drawable.ic_sound_bars_anim);
                        ongoingSessionStatus = new OngoingSessionStatus(
                                device.isHostForOngoingSession());
                        setTwoLineLayout(device.getName() /* title */,
                                true /* showSeekBar */, false /* showProgressBar */,
                                true /* showSubtitle */, false /* showStatus */,
                                true /* showEndTouchArea */);
                                true /* showSeekBar */,
                                true /* showSubtitle */, false /* showStatus */);
                        connectionState = ConnectionState.CONNECTED;
                        initSeekbar(device, isCurrentSeekbarInvisible);
                    } else {
                        if (currentlyConnected) {
                            mCurrentActivePosition = position;
                            updateUnmutedVolumeIcon(device);
                            connectionState = ConnectionState.CONNECTED;
                        } else {
                            setUpDeviceIcon(device);
                        }
@@ -276,7 +271,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
                                        ? DEVICE_CONNECTED_ALPHA : DEVICE_DISCONNECTED_ALPHA);
                        setTwoLineLayout(device.getName(),
                                currentlyConnected  /* showSeekBar */,
                                false /* showProgressBar */, true /* showSubtitle */,
                                true /* showSubtitle */,
                                deviceStatusIcon != null /* showStatus */);
                    }
                } else if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
@@ -285,25 +280,22 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
                    mSubTitleText.setText(R.string.media_output_dialog_connect_failed);
                    updateFullItemClickListener(v -> onItemClick(v, device));
                    setTwoLineLayout(device.getName(), false /* showSeekBar */,
                            false /* showProgressBar */, true /* showSubtitle */,
                            true /* showSubtitle */,
                            true /* showStatus */);
                } else if (device.getState() == MediaDeviceState.STATE_GROUPING) {
                    connectionState = ConnectionState.CONNECTING;
                    setUpDeviceIcon(device);
                    updateProgressBarColor();
                    setSingleLineLayout(device.getName(), false /* showSeekBar*/,
                            true /* showProgressBar */, false /* showCheckBox */,
                            false /* showEndTouchArea */);
                    setSingleLineLayout(device.getName(), false /* showSeekBar*/);
                } else if (mController.getSelectedMediaDevice().size() > 1 && isSelected) {
                    // selected device in group
                    boolean showEndArea =
                            !Flags.enableOutputSwitcherSessionGrouping() || isDeselectable;
                    updateUnmutedVolumeIcon(device);
                    updateEndAreaForGroupCheckbox(device, true /* isSelected */, isDeselectable);
                    groupStatus = new GroupStatus(
                            true /* selected */,
                            isDeselectable /* deselectable */);
                    disableFocusPropertyForView(mContainerLayout);
                    setUpContentDescriptionForView(mSeekBar, device);
                    setSingleLineLayout(device.getName(), true /* showSeekBar */,
                            false /* showProgressBar */, true /* showCheckBox */,
                            showEndArea /* showEndTouchArea */);
                    setSingleLineLayout(device.getName(), true /* showSeekBar */);
                    connectionState = ConnectionState.CONNECTED;
                    initSeekbar(device, isCurrentSeekbarInvisible);
                } else if (!mController.hasAdjustVolumeUserRestriction()
                        && currentlyConnected) {
@@ -317,50 +309,43 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
                    } else if (device.hasOngoingSession()) {
                        mCurrentActivePosition = position;
                        updateUnmutedVolumeIcon(device);
                        updateEndClickAreaAsSessionEditing(device, device.isHostForOngoingSession()
                                ? R.drawable.media_output_status_edit_session
                                : R.drawable.ic_sound_bars_anim);
                        mEndClickIcon.setVisibility(View.VISIBLE);
                        setSingleLineLayout(device.getName(), true /* showSeekBar */,
                                false /* showProgressBar */, false /* showCheckBox */,
                                true /* showEndTouchArea */);
                        ongoingSessionStatus = new OngoingSessionStatus(
                                device.isHostForOngoingSession());
                        setSingleLineLayout(device.getName(), true /* showSeekBar */);
                        connectionState = ConnectionState.CONNECTED;
                        initSeekbar(device, isCurrentSeekbarInvisible);
                    } else if (mController.isCurrentConnectedDeviceRemote()
                            && !mController.getSelectableMediaDevice().isEmpty()) {
                        //If device is connected and there's other selectable devices, layout as
                        // one of selected devices.
                        updateUnmutedVolumeIcon(device);
                        updateEndAreaForGroupCheckbox(device, true /* isSelected */,
                                isDeselectable);
                        groupStatus = new GroupStatus(
                                true /* selected */,
                                isDeselectable /* isDeselectable */);
                        disableFocusPropertyForView(mContainerLayout);
                        setUpContentDescriptionForView(mSeekBar, device);
                        setSingleLineLayout(device.getName(), true /* showSeekBar */,
                                false /* showProgressBar */, true /* showCheckBox */,
                                true /* showEndTouchArea */);
                        setSingleLineLayout(device.getName(), true /* showSeekBar */);
                        connectionState = ConnectionState.CONNECTED;
                        initSeekbar(device, isCurrentSeekbarInvisible);
                    } else {
                        updateUnmutedVolumeIcon(device);
                        disableFocusPropertyForView(mContainerLayout);
                        setUpContentDescriptionForView(mSeekBar, device);
                        mCurrentActivePosition = position;
                        setSingleLineLayout(device.getName(), true /* showSeekBar */,
                                false /* showProgressBar */, false /* showCheckBox */,
                                false /* showEndTouchArea */);
                        setSingleLineLayout(device.getName(), true /* showSeekBar */);
                        connectionState = ConnectionState.CONNECTED;
                        initSeekbar(device, isCurrentSeekbarInvisible);
                    }
                } else if (isSelectable) {
                    //groupable device
                    setUpDeviceIcon(device);
                    updateEndAreaForGroupCheckbox(device, false /* isSelected */,
                            true /* isDeselectable */);
                    groupStatus = new GroupStatus(false /* selected */, true /* deselectable */);
                    if (!Flags.disableTransferWhenAppsDoNotSupport()
                            || isTransferable
                            || hasRouteListingPreferenceItem) {
                        updateFullItemClickListener(v -> onItemClick(v, device));
                    }
                    setSingleLineLayout(device.getName(), false /* showSeekBar */,
                            false /* showProgressBar */, true /* showCheckBox */,
                            true /* showEndTouchArea */);
                    setSingleLineLayout(device.getName(), false /* showSeekBar */);
                } else {
                    setUpDeviceIcon(device);
                    setSingleLineLayout(device.getName());
@@ -379,6 +364,47 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
                                    ? DEVICE_CONNECTED_ALPHA : DEVICE_DISCONNECTED_ALPHA);
                }
            }

            if (isDeviceGroup) {
                updateEndAreaForDeviceGroup();
                updateItemBackground(ConnectionState.CONNECTED);
            } else {
                updateEndArea(device, connectionState, groupStatus, ongoingSessionStatus);
                updateLoadingIndicator(connectionState);
                updateItemBackground(connectionState);
            }
        }

        /** Renders the right side round pill button / checkbox. */
        private void updateEndArea(@NonNull MediaDevice device, ConnectionState connectionState,
                @Nullable GroupStatus groupStatus,
                @Nullable OngoingSessionStatus ongoingSessionStatus) {
            boolean showEndArea = false;
            boolean isCheckbox = false;
            // If both group status and the ongoing session status are present, only the ongoing
            // session controls are displayed. The current layout design doesn't allow both group
            // and ongoing session controls to be rendered simultaneously.
            if (ongoingSessionStatus != null && connectionState == ConnectionState.CONNECTED) {
                showEndArea = true;
                updateEndAreaForOngoingSession(device, ongoingSessionStatus.host());
            } else if (groupStatus != null && shouldShowGroupCheckbox(groupStatus)) {
                showEndArea = true;
                isCheckbox = true;
                updateEndAreaForGroupCheckBox(device, groupStatus);
            }
            updateEndAreaVisibility(showEndArea, isCheckbox);
        }

        private boolean shouldShowGroupCheckbox(@NonNull GroupStatus groupStatus) {
            if (Flags.enableOutputSwitcherSessionGrouping()) {
                return isGroupCheckboxEnabled(groupStatus);
            }
            return true;
        }

        private boolean isGroupCheckboxEnabled(@NonNull GroupStatus groupStatus) {
            boolean disabled = groupStatus.selected() && !groupStatus.deselectable();
            return !disabled;
        }

        public void setCheckBoxColor(CheckBox checkBox, int color) {
@@ -395,14 +421,26 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
            mStatusIcon.setAlpha(alphaValue);
        }

        private void updateEndClickAreaAsSessionEditing(MediaDevice device, @DrawableRes int id) {
            updateEndClickAreaWithIcon(
        private void updateEndAreaForDeviceGroup() {
            updateEndAreaWithIcon(
                    v -> {
                        mShouldGroupSelectedMediaItems = false;
                        notifyDataSetChanged();
                    },
                    R.drawable.media_output_item_expand_group,
                    R.string.accessibility_expand_group);
            updateEndAreaVisibility(true /* showEndArea */, false /* isCheckbox */);
        }

        private void updateEndAreaForOngoingSession(@NonNull MediaDevice device, boolean isHost) {
            updateEndAreaWithIcon(
                    v -> mController.tryToLaunchInAppRoutingIntent(device.getId(), v),
                    id,
                    isHost ? R.drawable.media_output_status_edit_session
                            : R.drawable.ic_sound_bars_anim,
                    R.string.accessibility_open_application);
        }

        private void updateEndClickAreaWithIcon(View.OnClickListener clickListener,
        private void updateEndAreaWithIcon(View.OnClickListener clickListener,
                @DrawableRes int iconDrawableId,
                @StringRes int accessibilityStringId) {
            updateEndAreaColor(mController.getColorSeekbarProgress());
@@ -449,27 +487,20 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
            }
        }

        private void updateProgressBarColor() {
            mProgressBar.getIndeterminateDrawable().setTintList(
                    ColorStateList.valueOf(mController.getColorItemContent()));
        }

        public void updateEndAreaForGroupCheckbox(MediaDevice device, boolean isSelected,
                boolean isDeselectable) {
            mEndTouchArea.setOnClickListener(null);
        public void updateEndAreaForGroupCheckBox(@NonNull MediaDevice device,
                @NonNull GroupStatus groupStatus) {
            boolean isEnabled = isGroupCheckboxEnabled(groupStatus);
            mEndTouchArea.setOnClickListener(
                    isDeselectable ? (v) -> mCheckBox.performClick() : null);
            mEndTouchArea.setImportantForAccessibility(
                    View.IMPORTANT_FOR_ACCESSIBILITY_YES);
            updateEndAreaColor(isSelected ? mController.getColorSeekbarProgress()
                    isEnabled ? (v) -> mCheckBox.performClick() : null);
            mEndTouchArea.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
            updateEndAreaColor(groupStatus.selected() ? mController.getColorSeekbarProgress()
                    : mController.getColorItemBackground());
            setUpContentDescriptionForView(mEndTouchArea, device);
            mCheckBox.setOnCheckedChangeListener(null);
            mCheckBox.setChecked(isSelected);
            mCheckBox.setChecked(groupStatus.selected());
            mCheckBox.setOnCheckedChangeListener(
                    isDeselectable ? (buttonView, isChecked) -> onGroupActionTriggered(!isSelected,
                            device) : null);
            mCheckBox.setEnabled(isDeselectable);
                    isEnabled ? (buttonView, isChecked) -> onGroupActionTriggered(
                            !groupStatus.selected(), device) : null);
            mCheckBox.setEnabled(isEnabled);
            setCheckBoxColor(mCheckBox, mController.getColorItemContent());
        }

@@ -483,6 +514,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
            mTitleText.setTextColor(mController.getColorItemContent());
            mCheckBox.setVisibility(View.GONE);
            setSingleLineLayout(mContext.getText(R.string.media_output_dialog_pairing_new));
            updateItemBackground(ConnectionState.DISCONNECTED);
            final Drawable addDrawable = mContext.getDrawable(R.drawable.ic_add);
            mTitleIcon.setImageDrawable(addDrawable);
            mTitleIcon.setImageTintList(
@@ -546,7 +578,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
            view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
        }

        private void setUpContentDescriptionForView(View view, MediaDevice device) {
        private void setUpContentDescriptionForView(View view, @NonNull MediaDevice device) {
            setUpContentDescriptionForView(
                    view,
                    mContext.getString(device.getDeviceType()
+51 −49

File changed.

Preview size limit exceeded, changes collapsed.