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

Commit 9777bbe3 authored by Sunny Shao's avatar Sunny Shao
Browse files

[Catalyst] Introduce a AccessibilitySeekBarPreference contains tool tip window

Test: atest PreviewSizeSeekBarControllerTest TextReadingPreviewControllerTest
Bug: 372776688
Flag: com.android.settings.flags.catalyst_text_reading_screen
Change-Id: Ie93d2f26b1521e931ce648f0140894b153259f81
parent dc80bddc
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@
        android:key="preview"
        android:selectable="false"/>

    <com.android.settings.widget.LabeledSeekBarPreference
    <com.android.settings.accessibility.AccessibilitySeekBarPreference
        android:key="font_size"
        android:summary="@string/short_summary_font_size"
        android:title="@string/title_font_size"
@@ -35,7 +35,7 @@
        settings:iconStartContentDescription="@string/font_size_make_smaller_desc"
        settings:keywords="@string/keywords_font_size" />

    <com.android.settings.widget.LabeledSeekBarPreference
    <com.android.settings.accessibility.AccessibilitySeekBarPreference
        android:key="display_size"
        android:summary="@string/screen_zoom_short_summary"
        android:title="@string/screen_zoom_title"
+66 −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.settings.accessibility

import android.content.Context
import android.os.Bundle
import android.os.Parcelable
import android.util.AttributeSet
import com.android.settings.widget.LabeledSeekBarPreference

/**
 * Add a custom AccessibilitySeekBarPreference with tool tip window for font size and display size.
 */
open class AccessibilitySeekBarPreference(context: Context, attrs: AttributeSet?) :
    LabeledSeekBarPreference(context, attrs) {

    var needsQSTooltipReshow = false
    private var tooltipWindow: AccessibilityQuickSettingsTooltipWindow? = null

    override fun onSaveInstanceState(): Parcelable {
        val state = Bundle()
        state.putParcelable(null, super.onSaveInstanceState())
        if (needsQSTooltipReshow || tooltipWindow?.isShowing == true) {
            state.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, /* value= */ true)
        }
        return state
    }

    override fun onRestoreInstanceState(state: Parcelable?) {
        val bundle = state as Bundle
        super.onRestoreInstanceState(bundle.getParcelable(null, Parcelable::class.java))
        if (bundle.containsKey(KEY_SAVED_QS_TOOLTIP_RESHOW)) {
            needsQSTooltipReshow = bundle.getBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW)
        }
    }

    /** To generate a tooltip window and return it. */
    fun createTooltipWindow(): AccessibilityQuickSettingsTooltipWindow =
        AccessibilityQuickSettingsTooltipWindow(context).also { tooltipWindow = it }

    /** To dismiss the tooltip window. */
    fun dismissTooltip() {
        val tooltip = tooltipWindow
        if (tooltip?.isShowing == true) {
            tooltip.dismiss()
            tooltipWindow = null
        }
    }

    companion object {
        private const val KEY_SAVED_QS_TOOLTIP_RESHOW = "qs_tooltip_reshow"
    }
}
+21 −36
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.settings.accessibility;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.widget.SeekBar;

@@ -28,31 +27,27 @@ import androidx.preference.PreferenceScreen;

import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.widget.LabeledSeekBarPreference;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnCreate;
import com.android.settingslib.core.lifecycle.events.OnDestroy;
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;

import com.google.android.setupcompat.util.WizardManagerHelper;

import java.util.Optional;

/**
 * The controller of {@link LabeledSeekBarPreference} that listens to display size and font size
 * settings changes and updates preview size threshold smoothly.
 * The controller of {@link AccessibilitySeekBarPreference} that listens to display size and font
 * size settings changes and updates preview size threshold smoothly.
 */
abstract class PreviewSizeSeekBarController extends BasePreferenceController implements
        TextReadingResetController.ResetStateListener, LifecycleObserver, OnCreate,
        OnDestroy, OnSaveInstanceState {
        TextReadingResetController.ResetStateListener, LifecycleObserver, OnStart, OnStop,
        OnDestroy {
    private final PreviewSizeData<? extends Number> mSizeData;
    private static final String KEY_SAVED_QS_TOOLTIP_RESHOW = "qs_tooltip_reshow";
    private boolean mSeekByTouch;
    private Optional<ProgressInteractionListener> mInteractionListener = Optional.empty();
    private LabeledSeekBarPreference mSeekBarPreference;
    private AccessibilitySeekBarPreference mSeekBarPreference;
    private int mLastProgress;
    private boolean mNeedsQSTooltipReshow = false;
    private AccessibilityQuickSettingsTooltipWindow mTooltipWindow;
    private final Handler mHandler;

    private String[] mStateLabels = null;
@@ -101,30 +96,21 @@ abstract class PreviewSizeSeekBarController extends BasePreferenceController imp
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // Restore the tooltip.
        if (savedInstanceState != null
                && savedInstanceState.containsKey(KEY_SAVED_QS_TOOLTIP_RESHOW)) {
            mNeedsQSTooltipReshow = savedInstanceState.getBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW);
    public void onStart() {
        if (mSeekBarPreference.getNeedsQSTooltipReshow()) {
            mHandler.post(this::showQuickSettingsTooltipIfNeeded);
        }
    }

    @Override
    public void onDestroy() {
        // remove runnables in the queue.
    public void onStop() {
        // all the messages/callbacks will be removed.
        mHandler.removeCallbacksAndMessages(null);
        final boolean isTooltipWindowShowing = mTooltipWindow != null && mTooltipWindow.isShowing();
        if (isTooltipWindowShowing) {
            mTooltipWindow.dismiss();
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        final boolean isTooltipWindowShowing = mTooltipWindow != null && mTooltipWindow.isShowing();
        if (mNeedsQSTooltipReshow || isTooltipWindowShowing) {
            outState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, /* value= */ true);
        }
    public void onDestroy() {
        mSeekBarPreference.dismissTooltip();
    }

    void setInteractionListener(ProgressInteractionListener interactionListener) {
@@ -148,9 +134,6 @@ abstract class PreviewSizeSeekBarController extends BasePreferenceController imp
        mSeekBarPreference.setProgress(initialIndex);
        mSeekBarPreference.setContinuousUpdates(true);
        mSeekBarPreference.setOnSeekBarChangeListener(mSeekBarChangeListener);
        if (mNeedsQSTooltipReshow) {
            mHandler.post(this::showQuickSettingsTooltipIfNeeded);
        }
        setSeekbarStateDescription(mSeekBarPreference.getProgress());
    }

@@ -216,7 +199,8 @@ abstract class PreviewSizeSeekBarController extends BasePreferenceController imp
            return;
        }

        if (!mNeedsQSTooltipReshow && AccessibilityQuickSettingUtils.hasValueInSharedPreferences(
        if (!mSeekBarPreference.getNeedsQSTooltipReshow()
                && AccessibilityQuickSettingUtils.hasValueInSharedPreferences(
                mContext, tileComponentName)) {
            // Returns if quick settings tooltip only show once.
            return;
@@ -228,14 +212,15 @@ abstract class PreviewSizeSeekBarController extends BasePreferenceController imp
        // is not ready when we would like to show the tooltip.  If the seekbar is not ready,
        // we give up showing the tooltip and also do not reshow it in the future.
        if (mSeekBarPreference.getSeekbar() != null) {
            mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(mContext);
            mTooltipWindow.setup(getTileTooltipContent(),
            final AccessibilityQuickSettingsTooltipWindow tooltipWindow =
                    mSeekBarPreference.createTooltipWindow();
            tooltipWindow.setup(getTileTooltipContent(),
                    R.drawable.accessibility_auto_added_qs_tooltip_illustration);
            mTooltipWindow.showAtTopCenter(mSeekBarPreference.getSeekbar());
            tooltipWindow.showAtTopCenter(mSeekBarPreference.getSeekbar());
        }
        AccessibilityQuickSettingUtils.optInValueToSharedPreferences(mContext,
                tileComponentName);
        mNeedsQSTooltipReshow = false;
        mSeekBarPreference.setNeedsQSTooltipReshow(false);
    }

    /** Returns the accessibility Quick Settings tile component name. */
+2 −3
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ import com.android.settings.accessibility.TextReadingPreferenceFragment.EntryPoi
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.instrumentation.SettingsStatsLog;
import com.android.settings.display.PreviewPagerAdapter;
import com.android.settings.widget.LabeledSeekBarPreference;

import java.util.Objects;

@@ -58,8 +57,8 @@ class TextReadingPreviewController extends BasePreferenceController implements
    private int mLastDisplayProgress;
    private long mLastCommitTime;
    private TextReadingPreviewPreference mPreviewPreference;
    private LabeledSeekBarPreference mFontSizePreference;
    private LabeledSeekBarPreference mDisplaySizePreference;
    private AccessibilitySeekBarPreference mFontSizePreference;
    private AccessibilitySeekBarPreference mDisplaySizePreference;

    @EntryPoint
    private int mEntryPoint;
+5 −8
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.widget.PopupWindow;
import android.widget.SeekBar;
@@ -44,7 +43,6 @@ import androidx.test.ext.junit.rules.ActivityScenarioRule;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settings.widget.LabeledSeekBarPreference;
import com.android.settingslib.testutils.shadow.ShadowInteractionJankMonitor;

import com.google.android.setupcompat.util.WizardManagerHelper;
@@ -77,7 +75,7 @@ public class PreviewSizeSeekBarControllerTest {
    private Activity mContext;
    private PreviewSizeSeekBarController mSeekBarController;
    private FontSizeData mFontSizeData;
    private LabeledSeekBarPreference mSeekBarPreference;
    private AccessibilitySeekBarPreference mSeekBarPreference;

    private PreferenceScreen mPreferenceScreen;
    private TestFragment mFragment;
@@ -109,7 +107,7 @@ public class PreviewSizeSeekBarControllerTest {
        mPreferenceScreen = spy(new PreferenceScreen(mContext, /* attrs= */ null));
        when(mPreferenceScreen.getPreferenceManager()).thenReturn(mPreferenceManager);
        doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
        mSeekBarPreference = spy(new LabeledSeekBarPreference(mContext, /* attrs= */ null));
        mSeekBarPreference = spy(new AccessibilitySeekBarPreference(mContext, /* attrs= */ null));
        mSeekBarPreference.setKey(FONT_SIZE_KEY);

        LayoutInflater inflater = LayoutInflater.from(mContext);
@@ -246,12 +244,11 @@ public class PreviewSizeSeekBarControllerTest {

    @Test
    @Config(shadows = ShadowFragment.class)
    public void restoreValueFromSavedInstanceState_showTooltipView() {
        final Bundle savedInstanceState = new Bundle();
        savedInstanceState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, /* value= */ true);
        mSeekBarController.onCreate(savedInstanceState);
    public void enabledNeedsQSTooltipReshow_showTooltipView() {
        mSeekBarPreference.setNeedsQSTooltipReshow(true);

        mSeekBarController.displayPreference(mPreferenceScreen);
        mSeekBarController.onStart();
        ShadowLooper.idleMainLooper();

        assertThat(getLatestPopupWindow().isShowing()).isTrue();
Loading