Loading src/com/android/settings/fuelgauge/BatteryChartView.java +37 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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"); Loading @@ -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; Loading @@ -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(); Loading @@ -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; Loading Loading @@ -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() { Loading @@ -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(); } Loading @@ -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); Loading tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java +60 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ public final class BatteryChartViewTest { mBatteryChartView.onAttachedToWindow(); assertThat(mBatteryChartView.isClickable()).isFalse(); assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNotNull(); } @Test Loading @@ -141,6 +142,7 @@ public final class BatteryChartViewTest { mBatteryChartView.onAttachedToWindow(); assertThat(mBatteryChartView.isClickable()).isTrue(); assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNull(); } @Test Loading @@ -155,6 +157,7 @@ public final class BatteryChartViewTest { mBatteryChartView.onAttachedToWindow(); assertThat(mBatteryChartView.isClickable()).isTrue(); assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNull(); } @Test Loading @@ -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); } } Loading
src/com/android/settings/fuelgauge/BatteryChartView.java +37 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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"); Loading @@ -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; Loading @@ -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(); Loading @@ -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; Loading Loading @@ -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() { Loading @@ -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(); } Loading @@ -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); Loading
tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java +60 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ public final class BatteryChartViewTest { mBatteryChartView.onAttachedToWindow(); assertThat(mBatteryChartView.isClickable()).isFalse(); assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNotNull(); } @Test Loading @@ -141,6 +142,7 @@ public final class BatteryChartViewTest { mBatteryChartView.onAttachedToWindow(); assertThat(mBatteryChartView.isClickable()).isTrue(); assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNull(); } @Test Loading @@ -155,6 +157,7 @@ public final class BatteryChartViewTest { mBatteryChartView.onAttachedToWindow(); assertThat(mBatteryChartView.isClickable()).isTrue(); assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNull(); } @Test Loading @@ -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); } }