Merge "Make chart time slot not clickable when accessibility servie is enabled" into sc-dev
diff --git a/src/com/android/settings/fuelgauge/BatteryChartView.java b/src/com/android/settings/fuelgauge/BatteryChartView.java
index 1048017..1590a57 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartView.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartView.java
@@ -24,6 +24,7 @@
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.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 @@
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 @@
// 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 @@
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 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 @@
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 @@
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);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
index 877ebc2..3998a33 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
@@ -130,6 +130,7 @@
mBatteryChartView.onAttachedToWindow();
assertThat(mBatteryChartView.isClickable()).isFalse();
+ assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNotNull();
}
@Test
@@ -141,6 +142,7 @@
mBatteryChartView.onAttachedToWindow();
assertThat(mBatteryChartView.isClickable()).isTrue();
+ assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNull();
}
@Test
@@ -155,6 +157,7 @@
mBatteryChartView.onAttachedToWindow();
assertThat(mBatteryChartView.isClickable()).isTrue();
+ assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNull();
}
@Test
@@ -166,5 +169,62 @@
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);
}
}