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

Commit e853b6b2 authored by mxyyiyi's avatar mxyyiyi
Browse files

[A11y] Add battery chart slot selected status in content description.

- Let talkback annouce the slot status before battery slot info.
"Selected": If current slot is selected or after the double-tap action to selected a slot.
"Unselected": If current slot is not the seletectd one or after double-tapping an already selected slot(which will selected ALL instead)

Fix: 386027256
Test: Talkback
Flag: EXEMPT for simple fix
Change-Id: I32a665cdf21620aade8397e5bbe4cb44964b0a39
parent 744ed220
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -6600,8 +6600,12 @@
    <string name="battery_usage_timestamps_content_description"><xliff:g id="from_timestamp">%1$s</xliff:g> to <xliff:g id="to_timestamp">%2$s</xliff:g></string>
    <!-- [CHAR_LIMIT=NONE] The first slot is a week day (e.g. "Monday"); the second slot is a hourly time span (e.g. "6 AM - 8 AM"). -->
    <string name="battery_usage_day_and_hour"><xliff:g id="day">%1$s</xliff:g> <xliff:g id="hour">%2$s</xliff:g></string>
    <!-- [CHAR_LIMIT=NONE] Accessibility content description for each slot in battery chart view. -->
    <string name="battery_usage_time_info_and_battery_level"><xliff:g id="time_info" example="Battery usage for Monday 6 AM - 8 AM">%1$s</xliff:g> <xliff:g id="battery_level" example="Battery level percentage from 83% to 59%">%2$s</xliff:g></string>
    <!-- [CHAR_LIMIT=NONE] Accessibility content description for each slot in battery chart view. Please reuse the words in tc/6732629268310936155 -->
    <string name="battery_usage_status_time_info_and_battery_level"><xliff:g id="selected_status" example="Selected">%1$s</xliff:g>, <xliff:g id="time_info" example="Battery usage for Monday 6 AM - 8 AM">%2$s</xliff:g> <xliff:g id="battery_level" example="Battery level percentage from 83% to 59%">%3$s</xliff:g></string>
    <!-- [CHAR_LIMIT=NONE] Accessibility content description for the battery usage slot is selected. -->
    <string name="battery_chart_slot_status_selected">Selected</string>
    <!-- [CHAR_LIMIT=NONE] Accessibility content description for the battery usage slot is not selected -->
    <string name="battery_chart_slot_status_unselected">Unselected</string>
    <!-- [CHAR_LIMIT=NONE] Accessibility content description for battery chart view. -->
    <string name="battery_usage_chart">Battery usage chart</string>
    <!-- [CHAR_LIMIT=NONE] Accessibility content description for daily battery chart view. -->
+47 −40
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.settings.fuelgauge.batteryusage;

import static com.android.settings.fuelgauge.batteryusage.BatteryChartViewModel.SELECTED_INDEX_ALL;
import static com.android.settings.fuelgauge.batteryusage.BatteryChartViewModel.SELECTED_INDEX_INVALID;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.settings.SettingsEnums;
@@ -82,10 +85,10 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
    @VisibleForTesting TextView mChartSummaryTextView;
    @VisibleForTesting BatteryChartView mDailyChartView;
    @VisibleForTesting BatteryChartView mHourlyChartView;
    @VisibleForTesting int mDailyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
    @VisibleForTesting int mHourlyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
    @VisibleForTesting int mDailyHighlightSlotIndex = BatteryChartViewModel.SELECTED_INDEX_INVALID;
    @VisibleForTesting int mHourlyHighlightSlotIndex = BatteryChartViewModel.SELECTED_INDEX_INVALID;
    @VisibleForTesting int mDailyChartIndex = SELECTED_INDEX_ALL;
    @VisibleForTesting int mHourlyChartIndex = SELECTED_INDEX_ALL;
    @VisibleForTesting int mDailyHighlightSlotIndex = SELECTED_INDEX_INVALID;
    @VisibleForTesting int mHourlyHighlightSlotIndex = SELECTED_INDEX_INVALID;

    private boolean mIs24HourFormat;
    private View mBatteryChartViewGroup;
@@ -198,8 +201,8 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
                getTotalHours(batteryLevelData));

        if (batteryLevelData == null) {
            mDailyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
            mHourlyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
            mDailyChartIndex = SELECTED_INDEX_ALL;
            mHourlyChartIndex = SELECTED_INDEX_ALL;
            mDailyViewModel = null;
            mHourlyViewModels = null;
            refreshUi();
@@ -226,9 +229,9 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
    }

    boolean isHighlightSlotFocused() {
        return (mDailyHighlightSlotIndex != BatteryChartViewModel.SELECTED_INDEX_INVALID
        return (mDailyHighlightSlotIndex != SELECTED_INDEX_INVALID
                && mDailyHighlightSlotIndex == mDailyChartIndex
                && mHourlyHighlightSlotIndex != BatteryChartViewModel.SELECTED_INDEX_INVALID
                && mHourlyHighlightSlotIndex != SELECTED_INDEX_INVALID
                && mHourlyHighlightSlotIndex == mHourlyChartIndex);
    }

@@ -242,8 +245,8 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
    }

    void selectHighlightSlotIndex() {
        if (mDailyHighlightSlotIndex == BatteryChartViewModel.SELECTED_INDEX_INVALID
                || mHourlyHighlightSlotIndex == BatteryChartViewModel.SELECTED_INDEX_INVALID) {
        if (mDailyHighlightSlotIndex == SELECTED_INDEX_INVALID
                || mHourlyHighlightSlotIndex == SELECTED_INDEX_INVALID) {
            return;
        }
        if (mDailyHighlightSlotIndex == mDailyChartIndex
@@ -258,8 +261,11 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
                        "onDailyChartSelect:%d, onHourlyChartSelect:%d",
                        mDailyChartIndex, mHourlyChartIndex));
        refreshUi();
        // The highlight slot must be selected.
        mHandler.post(
                () -> mDailyChartView.setAccessibilityPaneTitle(getAccessibilityAnnounceMessage()));
                () ->
                        mDailyChartView.setAccessibilityPaneTitle(
                                getAccessibilityAnnounceMessage(/* isSlotSelected= */ true)));
        if (mOnSelectedIndexUpdatedListener != null) {
            mOnSelectedIndexUpdatedListener.onSelectedIndexUpdated();
        }
@@ -295,15 +301,16 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
                    }
                    Log.d(TAG, "onDailyChartSelect:" + trapezoidIndex);
                    mDailyChartIndex = trapezoidIndex;
                    mHourlyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
                    mHourlyChartIndex = SELECTED_INDEX_ALL;
                    refreshUi();
                    mHandler.post(
                            () ->
                                    mDailyChartView.setAccessibilityPaneTitle(
                                            getAccessibilityAnnounceMessage()));
                                            getAccessibilityAnnounceMessage(
                                                    mDailyChartIndex != SELECTED_INDEX_ALL)));
                    mMetricsFeatureProvider.action(
                            mPrefContext,
                            trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_ALL
                            trapezoidIndex == SELECTED_INDEX_ALL
                                    ? SettingsEnums.ACTION_BATTERY_USAGE_DAILY_SHOW_ALL
                                    : SettingsEnums.ACTION_BATTERY_USAGE_DAILY_TIME_SLOT,
                            mDailyChartIndex);
@@ -314,7 +321,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
        mHourlyChartView = hourlyChartView;
        mHourlyChartView.setOnSelectListener(
                trapezoidIndex -> {
                    if (mDailyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL) {
                    if (mDailyChartIndex == SELECTED_INDEX_ALL) {
                        // This will happen when a daily slot and an hour slot are clicked together.
                        return;
                    }
@@ -327,10 +334,11 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
                    mHandler.post(
                            () ->
                                    mHourlyChartView.setAccessibilityPaneTitle(
                                            getAccessibilityAnnounceMessage()));
                                            getAccessibilityAnnounceMessage(
                                                    mHourlyChartIndex != SELECTED_INDEX_ALL)));
                    mMetricsFeatureProvider.action(
                            mPrefContext,
                            trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_ALL
                            trapezoidIndex == SELECTED_INDEX_ALL
                                    ? SettingsEnums.ACTION_BATTERY_USAGE_SHOW_ALL
                                    : SettingsEnums.ACTION_BATTERY_USAGE_TIME_SLOT,
                            mHourlyChartIndex);
@@ -378,27 +386,27 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
        } else {
            mDailyChartView.setVisibility(View.VISIBLE);
            if (mDailyChartIndex >= mDailyViewModel.size()) {
                mDailyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
                mDailyChartIndex = SELECTED_INDEX_ALL;
            }
            mDailyViewModel.setSelectedIndex(mDailyChartIndex);
            mDailyViewModel.setHighlightSlotIndex(mDailyHighlightSlotIndex);
            mDailyChartView.setViewModel(mDailyViewModel);
        }

        if (mDailyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL) {
        if (mDailyChartIndex == SELECTED_INDEX_ALL) {
            // Multiple days are selected, hide the hourly chart view.
            animateBatteryHourlyChartView(/* visible= */ false);
        } else {
            animateBatteryHourlyChartView(/* visible= */ true);
            final BatteryChartViewModel hourlyViewModel = mHourlyViewModels.get(mDailyChartIndex);
            if (mHourlyChartIndex >= hourlyViewModel.size()) {
                mHourlyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
                mHourlyChartIndex = SELECTED_INDEX_ALL;
            }
            hourlyViewModel.setSelectedIndex(mHourlyChartIndex);
            hourlyViewModel.setHighlightSlotIndex(
                    (mDailyChartIndex == mDailyHighlightSlotIndex)
                            ? mHourlyHighlightSlotIndex
                            : BatteryChartViewModel.SELECTED_INDEX_INVALID);
                            : SELECTED_INDEX_INVALID);
            mHourlyChartView.setViewModel(hourlyViewModel);
        }
    }
@@ -416,7 +424,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
                isAccessibilityText
                        ? mDailyViewModel.getContentDescription(mDailyChartIndex)
                        : mDailyViewModel.getFullText(mDailyChartIndex);
        if (mHourlyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL) {
        if (mHourlyChartIndex == SELECTED_INDEX_ALL) {
            return selectedDayText;
        }

@@ -441,15 +449,19 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
            return "";
        }

        if (mDailyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL
                || mHourlyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL) {
        if (mDailyChartIndex == SELECTED_INDEX_ALL || mHourlyChartIndex == SELECTED_INDEX_ALL) {
            return mDailyViewModel.getSlotBatteryLevelText(mDailyChartIndex);
        }

        return mHourlyViewModels.get(mDailyChartIndex).getSlotBatteryLevelText(mHourlyChartIndex);
    }

    private String getAccessibilityAnnounceMessage() {
    private String getAccessibilityAnnounceMessage(final boolean isSlotSelected) {
        final String selectedInformation =
                mPrefContext.getString(
                        isSlotSelected
                                ? R.string.battery_chart_slot_status_selected
                                : R.string.battery_chart_slot_status_unselected);
        final String slotInformation = getSlotInformation(/* isAccessibilityText= */ true);
        final String slotInformationMessage =
                slotInformation == null
@@ -460,7 +472,8 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
        final String batteryLevelPercentageMessage = getBatteryLevelPercentageInfo();

        return mPrefContext.getString(
                R.string.battery_usage_time_info_and_battery_level,
                R.string.battery_usage_status_time_info_and_battery_level,
                selectedInformation,
                slotInformationMessage,
                batteryLevelPercentageMessage);
    }
@@ -533,9 +546,8 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
    }

    private boolean isAllSelected() {
        return (isBatteryLevelDataInOneDay()
                        || mDailyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL)
                && mHourlyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL;
        return (isBatteryLevelDataInOneDay() || mDailyChartIndex == SELECTED_INDEX_ALL)
                && mHourlyChartIndex == SELECTED_INDEX_ALL;
    }

    @VisibleForTesting
@@ -571,9 +583,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
            return null;
        }
        BatteryDiffData allBatteryDiffData =
                batteryUsageData
                        .get(BatteryChartViewModel.SELECTED_INDEX_ALL)
                        .get(BatteryChartViewModel.SELECTED_INDEX_ALL);
                batteryUsageData.get(SELECTED_INDEX_ALL).get(SELECTED_INDEX_ALL);
        return allBatteryDiffData == null ? null : allBatteryDiffData.getAppDiffEntryList();
    }

@@ -613,12 +623,9 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll

        @Override
        public String generateSlotBatteryLevelText(List<Integer> levels, int index) {
            final int fromBatteryLevelIndex =
                    index == BatteryChartViewModel.SELECTED_INDEX_ALL ? 0 : index;
            final int fromBatteryLevelIndex = index == SELECTED_INDEX_ALL ? 0 : index;
            final int toBatteryLevelIndex =
                    index == BatteryChartViewModel.SELECTED_INDEX_ALL
                            ? levels.size() - 1
                            : index + 1;
                    index == SELECTED_INDEX_ALL ? levels.size() - 1 : index + 1;
            return mPrefContext.getString(
                    R.string.battery_level_percentage,
                    generateBatteryLevelText(levels.get(fromBatteryLevelIndex)),
+18 −17
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@ package com.android.settings.fuelgauge.batteryusage;

import static com.android.settings.Utils.formatPercentage;
import static com.android.settings.fuelgauge.batteryusage.BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS;
import static com.android.settings.fuelgauge.batteryusage.BatteryChartViewModel.SELECTED_INDEX_ALL;
import static com.android.settings.fuelgauge.batteryusage.BatteryChartViewModel.SELECTED_INDEX_INVALID;
import static com.android.settingslib.fuelgauge.BatteryStatus.BATTERY_LEVEL_UNKNOWN;

import static java.lang.Math.abs;
@@ -81,7 +83,7 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
            getContext().getResources().getConfiguration().getLayoutDirection();

    private BatteryChartViewModel mViewModel;
    private int mHoveredIndex = BatteryChartViewModel.SELECTED_INDEX_INVALID;
    private int mHoveredIndex = SELECTED_INDEX_INVALID;
    private int mDividerWidth;
    private int mDividerHeight;
    private float mTrapezoidVOffset;
@@ -245,9 +247,9 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
                // sent here.
                return true;
            case MotionEvent.ACTION_HOVER_EXIT:
                if (mHoveredIndex != BatteryChartViewModel.SELECTED_INDEX_INVALID) {
                if (mHoveredIndex != SELECTED_INDEX_INVALID) {
                    sendAccessibilityEventForHover(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
                    mHoveredIndex = BatteryChartViewModel.SELECTED_INDEX_INVALID; // reset
                    mHoveredIndex = SELECTED_INDEX_INVALID; // reset
                    invalidate();
                }
                // Ignore the super.onHoverEvent() because the hovered trapezoid has already been
@@ -262,7 +264,7 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
    public void onHoverChanged(boolean hovered) {
        super.onHoverChanged(hovered);
        if (!hovered) {
            mHoveredIndex = BatteryChartViewModel.SELECTED_INDEX_INVALID; // reset
            mHoveredIndex = SELECTED_INDEX_INVALID; // reset
            invalidate();
        }
    }
@@ -295,9 +297,7 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
        if (mOnSelectListener != null) {
            // Selects all if users click the same trapezoid item two times.
            mOnSelectListener.onSelect(
                    index == mViewModel.selectedIndex()
                            ? BatteryChartViewModel.SELECTED_INDEX_ALL
                            : index);
                    index == mViewModel.selectedIndex() ? SELECTED_INDEX_ALL : index);
        }
        view.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
    }
@@ -332,8 +332,8 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
        setBackgroundColor(Color.TRANSPARENT);
        mTrapezoidSolidColor = Utils.getColorAccentDefaultColor(context);
        mTrapezoidColor = Utils.getDisabled(context, mTrapezoidSolidColor);
        mTrapezoidHoverColor = context.getColor(
                com.android.internal.R.color.materialColorSecondaryContainer);
        mTrapezoidHoverColor =
                context.getColor(com.android.internal.R.color.materialColorSecondaryContainer);
        // Initializes the divider line paint.
        final Resources resources = getContext().getResources();
        mDividerWidth = resources.getDimensionPixelSize(R.dimen.chartview_divider_width);
@@ -623,8 +623,7 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
            // Configures the trapezoid paint color.
            final int trapezoidColor =
                    (mViewModel.selectedIndex() == index
                                    || mViewModel.selectedIndex()
                                            == BatteryChartViewModel.SELECTED_INDEX_ALL)
                                    || mViewModel.selectedIndex() == SELECTED_INDEX_ALL)
                            ? mTrapezoidSolidColor
                            : mTrapezoidColor;
            final boolean isHoverState =
@@ -659,9 +658,7 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
    }

    private boolean isHighlightSlotValid() {
        return mViewModel != null
                && mViewModel.getHighlightSlotIndex()
                        != BatteryChartViewModel.SELECTED_INDEX_INVALID;
        return mViewModel != null && mViewModel.getHighlightSlotIndex() != SELECTED_INDEX_INVALID;
    }

    private void drawTransomLine(Canvas canvas) {
@@ -715,7 +712,7 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
    // Searches the corresponding trapezoid index from x location.
    private int getTrapezoidIndex(float x) {
        if (mTrapezoidSlots == null) {
            return BatteryChartViewModel.SELECTED_INDEX_INVALID;
            return SELECTED_INDEX_INVALID;
        }
        for (int index = 0; index < mTrapezoidSlots.length; index++) {
            final TrapezoidSlot slot = mTrapezoidSlots[index];
@@ -723,7 +720,7 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
                return index;
            }
        }
        return BatteryChartViewModel.SELECTED_INDEX_INVALID;
        return SELECTED_INDEX_INVALID;
    }

    private void initializeAxisLabelsBounds() {
@@ -796,7 +793,11 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
            childInfo.setText(slotTimeInfo);
            childInfo.setContentDescription(
                    mContext.getString(
                            R.string.battery_usage_time_info_and_battery_level,
                            R.string.battery_usage_status_time_info_and_battery_level,
                            mContext.getString(
                                    mViewModel.selectedIndex() == virtualViewId
                                            ? R.string.battery_chart_slot_status_selected
                                            : R.string.battery_chart_slot_status_unselected),
                            slotTimeInfo,
                            batteryLevelInfo));
            childInfo.setAccessibilityFocused(virtualViewId == mAccessibilityFocusNodeViewId);