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

Commit 1e320e60 authored by Anton Potapov's avatar Anton Potapov Committed by Android (Google) Code Review
Browse files

Merge "Change a11y step for the SeekBar in VolumeDialogImpl" into main

parents d4631958 60518340
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.volume;

import android.media.AudioManager;
import android.util.MathUtils;
import android.view.View;

/**
@@ -46,4 +47,27 @@ class Util extends com.android.settingslib.volume.Util {
        if (v == null || (v.getVisibility() == View.VISIBLE) == vis) return;
        v.setVisibility(vis ? View.VISIBLE : View.GONE);
    }

    /**
     * Translates a value from one range to another.
     *
     * ```
     * Given: currentValue=3, currentRange=[0, 8], targetRange=[0, 100]
     * Result: 37.5
     * ```
     */
    public static float translateToRange(float value,
            float valueRangeStart,
            float valueRangeEnd,
            float targetRangeStart,
            float targetRangeEnd) {
        float currentRangeLength = valueRangeEnd - valueRangeStart;
        float targetRangeLength = targetRangeEnd - targetRangeStart;
        if (currentRangeLength == 0f || targetRangeLength == 0f) {
            return targetRangeStart;
        }
        float valueFraction = (value - valueRangeStart) / currentRangeLength;
        return MathUtils.constrain(targetRangeStart + valueFraction * targetRangeLength,
                targetRangeStart, targetRangeEnd);
    }
}
+20 −15
Original line number Diff line number Diff line
@@ -137,13 +137,13 @@ import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.volume.domain.interactor.VolumePanelNavigationInteractor;
import com.android.systemui.volume.ui.navigation.VolumeNavigator;

import dagger.Lazy;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

import dagger.Lazy;

/**
 * Visual presentation of the volume dialog.
 *
@@ -166,6 +166,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,

    private static final int DRAWER_ANIMATION_DURATION_SHORT = 175;
    private static final int DRAWER_ANIMATION_DURATION = 250;
    private static final int DISPLAY_RANGE_MULTIPLIER = 100;

    /** Shows volume dialog show animation. */
    private static final String TYPE_SHOW = "show";
@@ -826,12 +827,14 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
        writer.print("  mSilentMode: "); writer.println(mSilentMode);
    }

    private static int getImpliedLevel(SeekBar seekBar, int progress) {
        final int m = seekBar.getMax();
        final int n = m / 100 - 1;
        final int level = progress == 0 ? 0
                : progress == m ? (m / 100) : (1 + (int) ((progress / (float) m) * n));
        return level;
    private static int getVolumeFromProgress(StreamState state, SeekBar seekBar, int progress) {
        return (int) Util.translateToRange(progress, seekBar.getMin(), seekBar.getMax(),
                state.levelMin, state.levelMax);
    }

    private static int getProgressFromVolume(StreamState state, SeekBar seekBar, int volume) {
        return (int) Util.translateToRange(volume, state.levelMin, state.levelMax, seekBar.getMin(),
                seekBar.getMax());
    }

    @SuppressLint("InflateParams")
@@ -854,6 +857,8 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
        addSliderHapticsToRow(row);
        row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row));
        row.number = row.view.findViewById(R.id.volume_number);
        row.slider.setAccessibilityDelegate(
                new VolumeDialogSeekBarAccessibilityDelegate(DISPLAY_RANGE_MULTIPLIER));

        row.anim = null;

@@ -1916,12 +1921,12 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
                : false;

        // update slider max
        final int max = ss.levelMax * 100;
        final int max = ss.levelMax * DISPLAY_RANGE_MULTIPLIER;
        if (max != row.slider.getMax()) {
            row.slider.setMax(max);
        }
        // update slider min
        final int min = ss.levelMin * 100;
        final int min = ss.levelMin * DISPLAY_RANGE_MULTIPLIER;
        if (min != row.slider.getMin()) {
            row.slider.setMin(min);
        }
@@ -2069,7 +2074,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
            return;  // don't update if user is sliding
        }
        final int progress = row.slider.getProgress();
        final int level = getImpliedLevel(row.slider, progress);
        final int level = getVolumeFromProgress(row.ss, row.slider, progress);
        final boolean rowVisible = row.view.getVisibility() == VISIBLE;
        final boolean inGracePeriod = (SystemClock.uptimeMillis() - row.userAttempt)
                < USER_ATTEMPT_GRACE_PERIOD;
@@ -2085,7 +2090,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
                return;  // don't clamp if visible
            }
        }
        final int newProgress = vlevel * 100;
        final int newProgress = getProgressFromVolume(row.ss, row.slider, vlevel);
        if (progress != newProgress) {
            if (mShowing && rowVisible) {
                // animate!
@@ -2530,13 +2535,13 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
                    + " onProgressChanged " + progress + " fromUser=" + fromUser);
            if (!fromUser) return;
            if (mRow.ss.levelMin > 0) {
                final int minProgress = mRow.ss.levelMin * 100;
                final int minProgress = getProgressFromVolume(mRow.ss, seekBar, mRow.ss.levelMin);
                if (progress < minProgress) {
                    seekBar.setProgress(minProgress);
                    progress = minProgress;
                }
            }
            final int userLevel = getImpliedLevel(seekBar, progress);
            final int userLevel = getVolumeFromProgress(mRow.ss, seekBar, progress);
            if (mRow.ss.level != userLevel || mRow.ss.muted && userLevel > 0) {
                mRow.userAttempt = SystemClock.uptimeMillis();
                if (mRow.requestedLevel != userLevel) {
@@ -2569,7 +2574,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
            }
            mRow.tracking = false;
            mRow.userAttempt = SystemClock.uptimeMillis();
            final int userLevel = getImpliedLevel(seekBar, seekBar.getProgress());
            final int userLevel = getVolumeFromProgress(mRow.ss, seekBar, seekBar.getProgress());
            Events.writeEvent(Events.EVENT_TOUCH_LEVEL_DONE, mRow.stream, userLevel);
            if (mRow.ss.level != userLevel) {
                mHandler.sendMessageDelayed(mHandler.obtainMessage(H.RECHECK, mRow),
+55 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.systemui.volume

import android.os.Bundle
import android.view.View
import android.view.View.AccessibilityDelegate
import android.view.accessibility.AccessibilityNodeInfo
import android.widget.SeekBar
import com.android.internal.R

class VolumeDialogSeekBarAccessibilityDelegate(
    private val accessibilityStep: Int,
) : AccessibilityDelegate() {

    override fun performAccessibilityAction(host: View, action: Int, args: Bundle?): Boolean {
        require(host is SeekBar) { "This class only works with the SeekBar" }
        val seekBar: SeekBar = host
        if (
            action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD ||
                action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
        ) {
            var increment = accessibilityStep
            if (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) {
                increment = -increment
            }

            return super.performAccessibilityAction(
                host,
                R.id.accessibilityActionSetProgress,
                Bundle().apply {
                    putFloat(
                        AccessibilityNodeInfo.ACTION_ARGUMENT_PROGRESS_VALUE,
                        (seekBar.progress + increment).coerceIn(seekBar.min, seekBar.max).toFloat(),
                    )
                },
            )
        }
        return super.performAccessibilityAction(host, action, args)
    }
}
+52 −4
Original line number Diff line number Diff line
@@ -15,14 +15,14 @@
 */
package com.android.systemui.volume;

import static com.google.common.truth.Truth.assertThat;

import android.media.MediaMetadata;

import androidx.test.filters.SmallTest;

import com.android.systemui.SysuiTestCase;

import junit.framework.Assert;

import org.junit.Test;

@SmallTest
@@ -30,11 +30,59 @@ public class UtilTest extends SysuiTestCase {

    @Test
    public void testMediaMetadataToString_null() {
        Assert.assertEquals(null, Util.mediaMetadataToString(null));
        assertThat(Util.mediaMetadataToString(null)).isNull();
    }

    @Test
    public void testMediaMetadataToString_notNull() {
        Assert.assertNotNull(Util.mediaMetadataToString(new MediaMetadata.Builder().build()));
        assertThat(Util.mediaMetadataToString(new MediaMetadata.Builder().build())).isNotNull();
    }

    @Test
    public void translateToRange_translatesStartToStart() {
        assertThat(
                (int) Util.translateToRange(
                        /* value= */ 0,
                        /* valueRangeStart= */ 0,
                        /* valueRangeEnd= */ 7,
                        /* targetRangeStart= */ 0,
                        /* targetRangeEnd= */700)
        ).isEqualTo(0);
    }

    @Test
    public void translateToRange_translatesValueToValue() {
        assertThat(
                (int) Util.translateToRange(
                        /* value= */ 4,
                        /* valueRangeStart= */ 0,
                        /* valueRangeEnd= */ 7,
                        /* targetRangeStart= */ 0,
                        /* targetRangeEnd= */700)
        ).isEqualTo(400);
    }

    @Test
    public void translateToRange_translatesEndToEnd() {
        assertThat(
                (int) Util.translateToRange(
                        /* value= */ 7,
                        /* valueRangeStart= */ 0,
                        /* valueRangeEnd= */ 7,
                        /* targetRangeStart= */ 0,
                        /* targetRangeEnd= */700)
        ).isEqualTo(700);
    }

    @Test
    public void translateToRange_returnsStartForEmptyRange() {
        assertThat(
                (int) Util.translateToRange(
                        /* value= */ 7,
                        /* valueRangeStart= */ 7,
                        /* valueRangeEnd= */ 7,
                        /* targetRangeStart= */ 700,
                        /* targetRangeEnd= */700)
        ).isEqualTo(700);
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -248,6 +248,8 @@ public class VolumeDialogImplTest extends SysuiTestCase {
            VolumeDialogController.StreamState ss = new VolumeDialogController.StreamState();
            ss.name = STREAMS.get(i);
            ss.level = 1;
            ss.levelMin = 0;
            ss.levelMax = 25;
            state.states.append(i, ss);
        }
        return state;