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

Commit b5cf7eee authored by Yuhan Yang's avatar Yuhan Yang
Browse files

Implement autoclick delay seek bar functionality

Screencast: go/screencast-njq1ndi3njq3mjcwmdkyohwwntg0mjdjmy1jyq

Bug: 390460859
Test: atest AutoclickDelayDialogFragmentTest
Flag: com.android.server.accessibility.enable_autoclick_indicator
Change-Id: I013759b195c9ce761c5bb72179355bd4fed94ab5
parent b18aaa49
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@
        android:id="@+id/sliderContainer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        app:constraint_referenced_ids="accessibility_autoclick_custom_value,
                                        accessibility_autoclick_custom_value_decrease,
                                        accessibility_autoclick_custom_slider,
@@ -110,7 +111,6 @@
        android:id="@+id/accessibility_autoclick_custom_value"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="value"
        android:textColor="?android:attr/textColorPrimary"
        app:layout_constrainedHeight="true"
        app:layout_constrainedWidth="true"
+60 −7
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.settings.accessibility;

import static android.view.accessibility.AccessibilityManager.AUTOCLICK_DELAY_WITH_INDICATOR_DEFAULT;

import static com.android.settings.accessibility.AutoclickUtils.AUTOCLICK_DELAY_STEP;

import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.os.Bundle;
@@ -28,10 +30,13 @@ import android.view.View;
import android.view.accessibility.AccessibilityManager;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.SeekBar;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.constraintlayout.widget.Group;

import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
@@ -70,6 +75,11 @@ public class AutoclickDelayDialogFragment extends InstrumentedDialogFragment {
        getRadioButtonLabels(dialogView);
        RadioGroup radioGroup = dialogView.findViewById(
                R.id.autoclick_delay_before_click_value_group);
        SeekBar customProgressBar = dialogView.findViewById(
                R.id.accessibility_autoclick_custom_slider);
        TextView customValueTextView = dialogView.findViewById(
                R.id.accessibility_autoclick_custom_value);
        Group sliderContainer = dialogView.findViewById(R.id.sliderContainer);

        AlertDialog alertDialog = new AlertDialog.Builder(getContext())
                .setView(dialogView)
@@ -82,46 +92,89 @@ public class AutoclickDelayDialogFragment extends InstrumentedDialogFragment {
                            if (RADIO_BUTTON_ID_TO_DELAY_TIME
                                    .containsKey(checkedRadioButtonId)) {
                                delay = RADIO_BUTTON_ID_TO_DELAY_TIME.get(checkedRadioButtonId);
                            } else {
                                delay = seekBarProgressToDelay(customProgressBar.getProgress());
                            }

                            // TODO(b/390460859): Add custom seekbar for other delay time values.
                            updateAutoclickDelay(delay);
                        })
                .setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.dismiss())
                .create();
        radioGroup.setOnCheckedChangeListener((buttonView, checkedId) -> {
            customValueTextView.setText(delayTimeToString(
                    seekBarProgressToDelay(customProgressBar.getProgress())));
            sliderContainer.setVisibility(
                    isCustomButtonChecked(checkedId) ? View.VISIBLE : View.GONE);
        });

        customProgressBar.setOnSeekBarChangeListener(
            new SeekBar.OnSeekBarChangeListener() {
                @Override
                public void onProgressChanged(
                        @NonNull SeekBar seekBar, int progress, boolean fromUser) {
                    CharSequence threshold = delayTimeToString(seekBarProgressToDelay(progress));
                    customValueTextView.setText(threshold);
                }

                @Override
                public void onStartTrackingTouch(@NonNull SeekBar seekBar) {
                }

                @Override
                public void onStopTrackingTouch(@NonNull SeekBar seekBar) {
                }
            });

        if (savedInstanceState == null) {
            initStateBasedOnDelay(radioGroup);
            initStateBasedOnDelay(radioGroup, customValueTextView, customProgressBar);
        }

        return alertDialog;
    }

    private void initStateBasedOnDelay(@NonNull RadioGroup radioGroup) {
        // TODO(b/390460859): Add custom seekbar for other delay time values.
    private void initStateBasedOnDelay(@NonNull RadioGroup radioGroup,
            @NonNull TextView customValueTextView, @NonNull SeekBar customProgressBar) {
        final int autoclickDelay = Settings.Secure.getInt(getContext().getContentResolver(),
                Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
                AccessibilityManager.AUTOCLICK_DELAY_WITH_INDICATOR_DEFAULT);

        customValueTextView.setText(delayTimeToString(autoclickDelay));
        customProgressBar.setProgress(autoclickDelay / AUTOCLICK_DELAY_STEP);

        Integer radioButtonId = RADIO_BUTTON_ID_TO_DELAY_TIME.inverse().get(autoclickDelay);
        if (radioButtonId != null) {
            radioGroup.check(radioButtonId);
        } else {
            radioGroup.check(R.id.accessibility_autoclick_dialog_custom);
        }
    }

    private boolean isCustomButtonChecked(int checkedId) {
        return checkedId == R.id.accessibility_autoclick_dialog_custom;
    }

    private void getRadioButtonLabels(@NonNull View dialogView) {
        for (Integer radioButtonId : RADIO_BUTTON_ID_TO_DELAY_TIME.keySet()) {
            RadioButton radioButton = dialogView.findViewById(radioButtonId);
            if (radioButton != null) {
                radioButton.setText(AutoclickUtils.getAutoclickDelaySummary(
                        getContext(), R.string.accessibility_autoclick_delay_unit_second,
                radioButton.setText(delayTimeToString(
                        RADIO_BUTTON_ID_TO_DELAY_TIME.get(radioButtonId)));
            }
        }
    }

    /** Converts seek bar preference progress value to autoclick delay associated with it. */
    private int seekBarProgressToDelay(int progress) {
        return progress * AUTOCLICK_DELAY_STEP;
    }

    private CharSequence delayTimeToString(int delayMillis) {
        return AutoclickUtils.getAutoclickDelaySummary(getContext(),
                R.string.accessibility_autoclick_delay_unit_second, delayMillis);
    }

    /** Updates autoclick delay time. */
    public void updateAutoclickDelay(int delay) {
    private void updateAutoclickDelay(int delay) {
        Settings.Secure.putInt(
                getContext().getContentResolver(),
                Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
+47 −0
Original line number Diff line number Diff line
@@ -18,13 +18,18 @@ package com.android.settings.accessibility;

import static android.view.accessibility.AccessibilityManager.AUTOCLICK_DELAY_WITH_INDICATOR_DEFAULT;

import static com.android.settings.accessibility.AutoclickUtils.AUTOCLICK_DELAY_STEP;

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

import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.widget.RadioGroup;
import android.widget.SeekBar;

import androidx.appcompat.app.AlertDialog;
import androidx.constraintlayout.widget.Group;
import androidx.fragment.app.testing.FragmentScenario;
import androidx.lifecycle.Lifecycle;
import androidx.test.core.app.ApplicationProvider;
@@ -40,6 +45,7 @@ import org.robolectric.shadows.ShadowLooper;
@RunWith(RobolectricTestRunner.class)
public class AutoclickDelayDialogFragmentTest {

    private static final int TEST_SEEK_BAR_PROGRESS = 5;
    private AutoclickDelayDialogFragment mFragment;
    private AlertDialog mDialog;
    private FragmentScenario<AutoclickDelayDialogFragment> mFragmentScenario;
@@ -96,4 +102,45 @@ public class AutoclickDelayDialogFragmentTest {

        assertThat(autoclickDelay).isEqualTo(800);
    }

    @Test
    public void performClickOnNonCustomRadioButton_sliderGroupIsGone() {
        assertThat(mDialog.isShowing()).isTrue();
        Group sliderContainer = mDialog.findViewById(R.id.sliderContainer);
        assertThat(sliderContainer.getVisibility()).isEqualTo(View.GONE);

        RadioGroup radioGroup = mDialog.findViewById(
                R.id.autoclick_delay_before_click_value_group);
        radioGroup.check(R.id.accessibility_autoclick_dialog_custom);

        assertThat(sliderContainer.getVisibility()).isEqualTo(View.VISIBLE);

        radioGroup.check(R.id.accessibility_autoclick_dialog_800ms);
        assertThat(sliderContainer.getVisibility()).isEqualTo(View.GONE);
    }

    @Test
    public void performUpdateOnSeekBar_updatesAutoclickDelay() {
        assertThat(mDialog.isShowing()).isTrue();
        RadioGroup radioGroup = mDialog.findViewById(
                R.id.autoclick_delay_before_click_value_group);
        radioGroup.check(R.id.accessibility_autoclick_dialog_custom);

        SeekBar customProgressBar = mDialog.findViewById(
                R.id.accessibility_autoclick_custom_slider);
        assertThat(customProgressBar.getVisibility()).isEqualTo(View.VISIBLE);
        customProgressBar.setProgress(TEST_SEEK_BAR_PROGRESS);
        ShadowLooper.idleMainLooper();

        mDialog.getButton(AlertDialog.BUTTON_POSITIVE).performClick();
        ShadowLooper.idleMainLooper();

        final int autoclickDelay = Settings.Secure.getInt(
                ApplicationProvider.getApplicationContext().getContentResolver(),
                Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
                AUTOCLICK_DELAY_WITH_INDICATOR_DEFAULT);

        assertThat(autoclickDelay).isEqualTo(
                TEST_SEEK_BAR_PROGRESS * AUTOCLICK_DELAY_STEP);
    }
}