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

Commit 11de1a64 authored by ykhung's avatar ykhung Committed by YUKAI HUNG
Browse files

Make chart time slot not clickable when accessibility servie is enabled

after discuss with Shuan & Peggy, we will make the chat view is not
clickable since accessibility service is enabled for talkback, switch
access and voice access, since some gestures are conflict with our
design (double click to show all contents is conflict with a11y behavior)

Bug: 187814675
Test: make SettingsRoboTests
Change-Id: I7eecafc42cf4b4a0374ab46f07461e77907fc03a
parent 4cb355f8
Loading
Loading
Loading
Loading
+37 −4
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.HapticFeedbackConstants;
@@ -44,7 +45,8 @@ import java.util.List;
import java.util.Locale;

/** A widget component to draw chart graph. */
public class BatteryChartView extends AppCompatImageView implements View.OnClickListener {
public class BatteryChartView extends AppCompatImageView implements View.OnClickListener,
        AccessibilityManager.AccessibilityStateChangeListener {
    private static final String TAG = "BatteryChartView";
    private static final List<String> ACCESSIBILITY_SERVICE_NAMES =
        Arrays.asList("SwitchAccessService", "TalkBackService", "JustSpeakService");
@@ -52,6 +54,8 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
    private static final String[] PERCENTAGES = new String[] {"100%", "50%", "0%"};
    private static final int DEFAULT_TRAPEZOID_COUNT = 12;
    private static final int DEFAULT_TIMESTAMP_COUNT = 4;
    private static final int DIVIDER_COLOR = Color.parseColor("#CDCCC5");
    private static final long UPDATE_STATE_DELAYED_TIME = 500L;

    /** Selects all trapezoid shapes. */
    public static final int SELECTED_INDEX_ALL = -1;
@@ -74,7 +78,6 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
    // Colors for drawing the trapezoid shape and dividers.
    private int mTrapezoidColor;
    private int mTrapezoidSolidColor;
    private final int mDividerColor = Color.parseColor("#CDCCC5");
    // For drawing the percentage information.
    private int mTextPadding;
    private final Rect mIndent = new Rect();
@@ -85,11 +88,17 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
    private final Rect[] mTimestampsBounds =
        new Rect[] {new Rect(), new Rect(), new Rect(), new Rect()};

    @VisibleForTesting
    Handler mHandler = new Handler();
    @VisibleForTesting
    final Runnable mUpdateClickableStateRun = () -> updateClickableState();

    private int[] mLevels;
    private Paint mTextPaint;
    private Paint mDividerPaint;
    private Paint mTrapezoidPaint;
    private Paint mTrapezoidCurvePaint = null;
    @VisibleForTesting
    Paint mTrapezoidCurvePaint = null;
    private TrapezoidSlot[] mTrapezoidSlots;
    // Records the location to calculate selected index.
    private MotionEvent mTouchUpEvent;
@@ -257,6 +266,26 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        updateClickableState();
        mContext.getSystemService(AccessibilityManager.class)
            .addAccessibilityStateChangeListener(/*listener=*/ this);
    }

    @Override
    public void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mContext.getSystemService(AccessibilityManager.class)
            .removeAccessibilityStateChangeListener(/*listener=*/ this);
        mHandler.removeCallbacks(mUpdateClickableStateRun);
    }

    @Override
    public void onAccessibilityStateChanged(boolean enabled) {
        Log.d(TAG, "onAccessibilityStateChanged:" + enabled);
        mHandler.removeCallbacks(mUpdateClickableStateRun);
        // We should delay it a while since accessibility manager will spend
        // some times to bind with new enabled accessibility services.
        mHandler.postDelayed(
            mUpdateClickableStateRun, UPDATE_STATE_DELAYED_TIME);
    }

    private void updateClickableState() {
@@ -275,6 +304,10 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
            mTrapezoidCurvePaint.setColor(mTrapezoidSolidColor);
            mTrapezoidCurvePaint.setStyle(Paint.Style.STROKE);
            mTrapezoidCurvePaint.setStrokeWidth(mDividerWidth * 2);
        } else if (mIsSlotsClickabled) {
            mTrapezoidCurvePaint = null;
            // Sets levels again to force update the click state.
            setLevels(mLevels);
        }
        invalidate();
    }
@@ -299,7 +332,7 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
        mDividerHeight = resources.getDimensionPixelSize(R.dimen.chartview_divider_height);
        mDividerPaint = new Paint();
        mDividerPaint.setAntiAlias(true);
        mDividerPaint.setColor(mDividerColor);
        mDividerPaint.setColor(DIVIDER_COLOR);
        mDividerPaint.setStyle(Paint.Style.STROKE);
        mDividerPaint.setStrokeWidth(mDividerWidth);
        Log.i(TAG, "mDividerWidth:" + mDividerWidth);
+60 −0
Original line number Diff line number Diff line
@@ -130,6 +130,7 @@ public final class BatteryChartViewTest {

        mBatteryChartView.onAttachedToWindow();
        assertThat(mBatteryChartView.isClickable()).isFalse();
        assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNotNull();
    }

    @Test
@@ -141,6 +142,7 @@ public final class BatteryChartViewTest {

        mBatteryChartView.onAttachedToWindow();
        assertThat(mBatteryChartView.isClickable()).isTrue();
        assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNull();
    }

    @Test
@@ -155,6 +157,7 @@ public final class BatteryChartViewTest {

        mBatteryChartView.onAttachedToWindow();
        assertThat(mBatteryChartView.isClickable()).isTrue();
        assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNull();
    }

    @Test
@@ -166,5 +169,62 @@ public final class BatteryChartViewTest {

        mBatteryChartView.onAttachedToWindow();
        assertThat(mBatteryChartView.isClickable()).isFalse();
        assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNotNull();
    }

    @Test
    public void testClickable_restoreFromNonClickableState() {
        final int[] levels = new int[13];
        for (int index = 0; index < levels.length; index++) {
            levels[index] = index + 1;
        }
        mBatteryChartView.setTrapezoidCount(12);
        mBatteryChartView.setLevels(levels);
        mBatteryChartView.setClickableForce(true);
        when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
            .thenReturn(true);
        doReturn(true).when(mockAccessibilityManager).isEnabled();
        mBatteryChartView.onAttachedToWindow();
        // Ensures the testing environment is correct.
        assertThat(mBatteryChartView.isClickable()).isFalse();
        // Turns off accessibility service.
        doReturn(false).when(mockAccessibilityManager).isEnabled();

        mBatteryChartView.onAttachedToWindow();

        assertThat(mBatteryChartView.isClickable()).isTrue();
    }

    @Test
    public void testOnAttachedToWindow_addAccessibilityStateChangeListener() {
        mBatteryChartView.onAttachedToWindow();
        verify(mockAccessibilityManager)
            .addAccessibilityStateChangeListener(mBatteryChartView);
    }

    @Test
    public void testOnDetachedFromWindow_removeAccessibilityStateChangeListener() {
        mBatteryChartView.onAttachedToWindow();
        mBatteryChartView.mHandler.postDelayed(
            mBatteryChartView.mUpdateClickableStateRun, 1000);

        mBatteryChartView.onDetachedFromWindow();

        verify(mockAccessibilityManager)
            .removeAccessibilityStateChangeListener(mBatteryChartView);
        assertThat(mBatteryChartView.mHandler.hasCallbacks(
                mBatteryChartView.mUpdateClickableStateRun))
            .isFalse();
    }

    @Test
    public void testOnAccessibilityStateChanged_postUpdateStateRunnable() {
        mBatteryChartView.mHandler = spy(mBatteryChartView.mHandler);
        mBatteryChartView.onAccessibilityStateChanged(/*enabled=*/ true);

        verify(mBatteryChartView.mHandler)
            .removeCallbacks(mBatteryChartView.mUpdateClickableStateRun);
        verify(mBatteryChartView.mHandler)
            .postDelayed(mBatteryChartView.mUpdateClickableStateRun, 500L);
    }
}