Merge "Store whether the Dialog was previously dismissed" into sc-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f427d53..b49127a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6329,38 +6329,52 @@
<!-- Title for the battery management group [CHAR LIMIT=40] -->
<string name ="battery_detail_manage_title">Manage battery usage</string>
+ <!-- Description for battery total and background usage time for an app, i.e. 1 hr 15 min total • 39 min background from last full charge. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
+ <string name="battery_total_and_bg_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • <xliff:g id="time" example="39 min">^2</xliff:g> background\nfrom last full charge</string>
<!-- Description for battery total and background usage time for an app, i.e. 1 hr 15 min total • 39 min background for past 24 hr. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
- <string name="battery_total_and_bg_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • <xliff:g id="time" example="39 min">^2</xliff:g> background\nfor past 24 hr</string>
+ <string name="battery_total_and_bg_usage_24hr"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • <xliff:g id="time" example="39 min">^2</xliff:g> background\nfor past 24 hr</string>
<!-- Description for battery total and background usage time in a time period for an app, i.e. 1 hr 15 min total • 39 min background for 12 am-2 am. Note: ^1, ^2 and ^3 should be used in all translations [CHAR LIMIT=120] -->
<string name="battery_total_and_bg_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • <xliff:g id="time" example="39 min">^2</xliff:g> background\nfor <xliff:g id="time_period" example="12 am-2 am">^3</xliff:g></string>
- <!-- Description for battery total usage time is less than a minute for an app [CHAR LIMIT=120] -->
- <string name="battery_total_usage_less_minute">Total less than a minute for past 24 hr</string>
+ <!-- Description for battery total usage time is less than a minute for an app from last full charge [CHAR LIMIT=120] -->
+ <string name="battery_total_usage_less_minute">Total less than a minute from last full charge</string>
+ <!-- Description for battery total usage time is less than a minute for an app for past 24 hr [CHAR LIMIT=120] -->
+ <string name="battery_total_usage_less_minute_24hr">Total less than a minute for past 24 hr</string>
<!-- Description for battery total usage time is less than a minute in a time period for an app, i.e. Total less than a minute for 12 am-2 am. Note: ^1 should be used in all translations[CHAR LIMIT=120] -->
<string name="battery_total_usage_less_minute_with_period">Total less than a minute for <xliff:g id="time_period" example="12 am-2 am">^1</xliff:g></string>
- <!-- Description for battery background usage time is less than a minute for an app [CHAR LIMIT=120] -->
- <string name="battery_bg_usage_less_minute">Background less than a minute for past 24 hr</string>
+ <!-- Description for battery background usage time is less than a minute for an app from last full charge [CHAR LIMIT=120] -->
+ <string name="battery_bg_usage_less_minute">Background less than a minute from last full charge</string>
+ <!-- Description for battery background usage time is less than a minute for an app for past 24 hr [CHAR LIMIT=120] -->
+ <string name="battery_bg_usage_less_minute_24hr">Background less than a minute for past 24 hr</string>
<!-- Description for battery background usage time is less than a minute in a time period for an app, i.e. Background less than a minute for 12 am-2 am. Note: ^1 should be used in all translations[CHAR LIMIT=120] -->
<string name="battery_bg_usage_less_minute_with_period">Background less than a minute for <xliff:g id="time_period" example="12 am-2 am">^1</xliff:g></string>
+ <!-- Description for battery total usage time for an app, i.e. 1 hr 15 min total from last full charge. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
+ <string name="battery_total_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total from last full charge</string>
<!-- Description for battery total usage time for an app, i.e. 1 hr 15 min total for past 24 hr. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
- <string name="battery_total_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total for past 24 hr</string>
+ <string name="battery_total_usage_24hr"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total for past 24 hr</string>
<!-- Description for battery total usage time in a time period for an app, i.e. 1 hr 15 min total for 12 am-2 am. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
<string name="battery_total_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total for <xliff:g id="time_period" example="12 am-2 am">^2</xliff:g></string>
+ <!-- Description for battery background usage time for an app, i.e. 1 hr 15 min background from last full charge. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
+ <string name="battery_bg_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> background from last full charge</string>
<!-- Description for battery background usage time for an app, i.e. 1 hr 15 min background for past 24 hr. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
- <string name="battery_bg_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> background for past 24 hr</string>
+ <string name="battery_bg_usage_24hr"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> background for past 24 hr</string>
<!-- Description for battery background usage time in a time period for an app, i.e. 1 hr 15 min background for 12 am-2 am. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
<string name="battery_bg_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> background for <xliff:g id="time_period" example="12 am-2 am">^2</xliff:g></string>
+ <!-- Description for battery total usage with background usage time less than a minute for an app, i.e. 1 hr 15 min total • background less than a minute from last full charge. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
+ <string name="battery_total_usage_and_bg_less_minute_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute\nfrom last full charge</string>
<!-- Description for battery total usage with background usage time less than a minute for an app, i.e. 1 hr 15 min total • background less than a minute for past 24 hr. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
- <string name="battery_total_usage_and_bg_less_minute_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute\nfor past 24 hr</string>
+ <string name="battery_total_usage_and_bg_less_minute_usage_24hr"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute\nfor past 24 hr</string>
<!-- Description for battery total usage with background usage time less than a minute in a time period for an app, i.e. 1 hr 15 min total • background less than a minute for 12 am-2 am. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
<string name="battery_total_usage_and_bg_less_minute_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute\nfor <xliff:g id="time_period" example="12 am-2 am">^2</xliff:g></string>
+ <!-- Description for no any battery usage from last full charge [CHAR LIMIT=120] -->
+ <string name="battery_not_usage">No usage from last full charge</string>
<!-- Description for no any battery usage for past 24 hr [CHAR LIMIT=120] -->
- <string name="battery_not_usage">No usage for past 24 hr</string>
+ <string name="battery_not_usage_24hr">No usage for past 24 hr</string>
<!-- Graph subtext displayed to user when enhanced battery estimate is being used [CHAR LIMIT=120] -->
<string name="advanced_battery_graph_subtext">Battery left estimate is based on your device usage</string>
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index 7c2f052..2b83288 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -44,6 +44,7 @@
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
@@ -436,13 +437,18 @@
long foregroundTimeMs, long backgroundTimeMs, String slotTime) {
final long totalTimeMs = foregroundTimeMs + backgroundTimeMs;
final CharSequence usageTimeSummary;
+ final PowerUsageFeatureProvider powerFeatureProvider =
+ FeatureFactory.getFactory(getContext()).getPowerUsageFeatureProvider(getContext());
if (totalTimeMs == 0) {
- usageTimeSummary = getText(R.string.battery_not_usage);
+ usageTimeSummary = getText(powerFeatureProvider.isChartGraphEnabled(getContext())
+ ? R.string.battery_not_usage_24hr : R.string.battery_not_usage);
} else if (slotTime == null) {
- // Shows summary text with past 24 hr if slot time is null.
- usageTimeSummary =
- getAppPast24HrActiveSummary(foregroundTimeMs, backgroundTimeMs, totalTimeMs);
+ // Shows summary text with past 24 hr or full charge if slot time is null.
+ usageTimeSummary = powerFeatureProvider.isChartGraphEnabled(getContext())
+ ? getAppPast24HrActiveSummary(foregroundTimeMs, backgroundTimeMs, totalTimeMs)
+ : getAppFullChargeActiveSummary(
+ foregroundTimeMs, backgroundTimeMs, totalTimeMs);
} else {
// Shows summary text with slot time.
usageTimeSummary = getAppActiveSummaryWithSlotTime(
@@ -451,7 +457,7 @@
return usageTimeSummary;
}
- private CharSequence getAppPast24HrActiveSummary(
+ private CharSequence getAppFullChargeActiveSummary(
long foregroundTimeMs, long backgroundTimeMs, long totalTimeMs) {
// Shows background summary only if we don't have foreground usage time.
if (foregroundTimeMs == 0 && backgroundTimeMs != 0) {
@@ -494,6 +500,49 @@
}
}
+ private CharSequence getAppPast24HrActiveSummary(
+ long foregroundTimeMs, long backgroundTimeMs, long totalTimeMs) {
+ // Shows background summary only if we don't have foreground usage time.
+ if (foregroundTimeMs == 0 && backgroundTimeMs != 0) {
+ return backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS
+ ? getText(R.string.battery_bg_usage_less_minute_24hr)
+ : TextUtils.expandTemplate(getText(R.string.battery_bg_usage_24hr),
+ StringUtil.formatElapsedTime(
+ getContext(),
+ backgroundTimeMs,
+ /* withSeconds */ false,
+ /* collapseTimeUnit */ false));
+ // Shows total usage summary only if total usage time is small.
+ } else if (totalTimeMs < DateUtils.MINUTE_IN_MILLIS) {
+ return getText(R.string.battery_total_usage_less_minute_24hr);
+ // Shows different total usage summary when background usage time is small.
+ } else if (backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS) {
+ return TextUtils.expandTemplate(
+ getText(backgroundTimeMs == 0
+ ? R.string.battery_total_usage_24hr
+ : R.string.battery_total_usage_and_bg_less_minute_usage_24hr),
+ StringUtil.formatElapsedTime(
+ getContext(),
+ totalTimeMs,
+ /* withSeconds */ false,
+ /* collapseTimeUnit */ false));
+ // Shows default summary.
+ } else {
+ return TextUtils.expandTemplate(
+ getText(R.string.battery_total_and_bg_usage_24hr),
+ StringUtil.formatElapsedTime(
+ getContext(),
+ totalTimeMs,
+ /* withSeconds */ false,
+ /* collapseTimeUnit */ false),
+ StringUtil.formatElapsedTime(
+ getContext(),
+ backgroundTimeMs,
+ /* withSeconds */ false,
+ /* collapseTimeUnit */ false));
+ }
+ }
+
private CharSequence getAppActiveSummaryWithSlotTime(
long foregroundTimeMs, long backgroundTimeMs, long totalTimeMs, String slotTime) {
// Shows background summary only if we don't have foreground usage time.
diff --git a/src/com/android/settings/fuelgauge/BatteryChartView.java b/src/com/android/settings/fuelgauge/BatteryChartView.java
index cd76d0e..1048017 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartView.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartView.java
@@ -15,6 +15,7 @@
import static java.lang.Math.round;
+import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
@@ -28,23 +29,30 @@
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
+import android.view.accessibility.AccessibilityManager;
import android.widget.TextView;
import androidx.appcompat.widget.AppCompatImageView;
+import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.Utils;
+import java.util.Arrays;
+import java.util.List;
import java.util.Locale;
/** A widget component to draw chart graph. */
public class BatteryChartView extends AppCompatImageView implements View.OnClickListener {
private static final String TAG = "BatteryChartView";
+ private static final List<String> ACCESSIBILITY_SERVICE_NAMES =
+ Arrays.asList("SwitchAccessService", "TalkBackService", "JustSpeakService");
// For drawing the percentage information.
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;
+
/** Selects all trapezoid shapes. */
public static final int SELECTED_INDEX_ALL = -1;
public static final int SELECTED_INDEX_INVALID = -2;
@@ -57,10 +65,11 @@
private int mDividerWidth;
private int mDividerHeight;
private int mTrapezoidCount;
- private int mSelectedIndex;
private float mTrapezoidVOffset;
private float mTrapezoidHOffset;
- private boolean mIsSlotsClickable;
+ private boolean mIsSlotsClickabled;
+
+ @VisibleForTesting int mSelectedIndex;
// Colors for drawing the trapezoid shape and dividers.
private int mTrapezoidColor;
@@ -247,26 +256,37 @@
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
+ updateClickableState();
+ }
+
+ private void updateClickableState() {
final Context context = mContext;
- mIsSlotsClickable =
+ mIsSlotsClickabled =
FeatureFactory.getFactory(context)
- .getPowerUsageFeatureProvider(context)
- .isChartGraphSlotsEnabled(context);
- Log.d(TAG, "isChartGraphSlotsEnabled:" + mIsSlotsClickable);
+ .getPowerUsageFeatureProvider(context)
+ .isChartGraphSlotsEnabled(context)
+ && !isAccessibilityEnabled(context);
+ Log.d(TAG, "isChartGraphSlotsEnabled:" + mIsSlotsClickabled);
setClickable(isClickable());
// Initializes the trapezoid curve paint for non-clickable case.
- if (!mIsSlotsClickable && mTrapezoidCurvePaint == null) {
+ if (!mIsSlotsClickabled && mTrapezoidCurvePaint == null) {
mTrapezoidCurvePaint = new Paint();
mTrapezoidCurvePaint.setAntiAlias(true);
mTrapezoidCurvePaint.setColor(mTrapezoidSolidColor);
mTrapezoidCurvePaint.setStyle(Paint.Style.STROKE);
mTrapezoidCurvePaint.setStrokeWidth(mDividerWidth * 2);
}
+ invalidate();
}
@Override
public void setClickable(boolean clickable) {
- super.setClickable(mIsSlotsClickable && clickable);
+ super.setClickable(mIsSlotsClickabled && clickable);
+ }
+
+ @VisibleForTesting
+ void setClickableForce(boolean clickable) {
+ super.setClickable(clickable);
}
private void initializeColors(Context context) {
@@ -412,7 +432,7 @@
}
// Configures the trapezoid paint color.
final int trapezoidColor =
- !mIsSlotsClickable
+ !mIsSlotsClickabled
? mTrapezoidColor
: mSelectedIndex == index || mSelectedIndex == SELECTED_INDEX_ALL
? mTrapezoidSolidColor : mTrapezoidColor;
@@ -469,6 +489,29 @@
&& mLevels[trapezoidIndex + 1] != 0;
}
+ @VisibleForTesting
+ static boolean isAccessibilityEnabled(Context context) {
+ final AccessibilityManager accessibilityManager =
+ context.getSystemService(AccessibilityManager.class);
+ if (!accessibilityManager.isEnabled()) {
+ return false;
+ }
+ final List<AccessibilityServiceInfo> serviceInfoList =
+ accessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_SPOKEN
+ | AccessibilityServiceInfo.FEEDBACK_GENERIC);
+ for (AccessibilityServiceInfo info : serviceInfoList) {
+ for (String serviceName : ACCESSIBILITY_SERVICE_NAMES) {
+ final String serviceId = info.getId();
+ if (serviceId != null && serviceId.contains(serviceName)) {
+ Log.d(TAG, "acccessibilityEnabled:" + serviceId);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
// A container class for each trapezoid left and right location.
private static final class TrapezoidSlot {
public float mLeft;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index 00c71df..e5ca4e3 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -128,6 +128,7 @@
private RadioButtonPreference mUnrestrictedPreference;
private AdvancedPowerUsageDetail mFragment;
private SettingsActivity mTestActivity;
+ private FakeFeatureFactory mFeatureFactory;
@Before
public void setUp() {
@@ -135,7 +136,7 @@
mContext = spy(RuntimeEnvironment.application);
when(mContext.getPackageName()).thenReturn("foo");
- FakeFeatureFactory.setupForTest();
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
mFragment = spy(new AdvancedPowerUsageDetail());
doReturn(mContext).when(mFragment).getContext();
@@ -144,6 +145,8 @@
doReturn(APP_LABEL).when(mBundle).getString(nullable(String.class));
when(mFragment.getArguments()).thenReturn(mBundle);
doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+ when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+ .thenReturn(true);
ShadowEntityHeaderController.setUseMock(mEntityHeaderController);
doReturn(mEntityHeaderController).when(mEntityHeaderController)
@@ -270,6 +273,144 @@
}
@Test
+ public void testInitHeader_noUsageTimeAndGraphDisabled_hasCorrectSummary() {
+ when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+ .thenReturn(false);
+
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, /* value */ 0);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, /* value */ 0);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("No usage from last full charge");
+ }
+
+ @Test
+ public void testInitHeader_bgTwoMinFgZeroAndGraphDisabled_hasCorrectSummary() {
+ when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+ .thenReturn(false);
+
+ final long backgroundTimeTwoMinutes = 120000;
+ final long foregroundTimeZero = 0;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeTwoMinutes);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("2 min background from last full charge");
+ }
+
+ @Test
+ public void testInitHeader_bgLessThanAMinFgZeroAndGraphDisabled_hasCorrectSummary() {
+ when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+ .thenReturn(false);
+
+ final long backgroundTimeLessThanAMinute = 59999;
+ final long foregroundTimeZero = 0;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(
+ AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanAMinute);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("Background less than a minute from last full charge");
+ }
+
+ @Test
+ public void testInitHeader_totalUsageLessThanAMinAndGraphDisabled_hasCorrectSummary() {
+ when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+ .thenReturn(false);
+
+ final long backgroundTimeLessThanHalfMinute = 20000;
+ final long foregroundTimeLessThanHalfMinute = 20000;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(
+ AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanHalfMinute);
+ bundle.putLong(
+ AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeLessThanHalfMinute);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("Total less than a minute from last full charge");
+ }
+
+ @Test
+ public void testInitHeader_TotalAMinutesBgLessThanAMinAndGraphDisabled_hasCorrectSummary() {
+ when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+ .thenReturn(false);
+
+ final long backgroundTimeZero = 59999;
+ final long foregroundTimeTwoMinutes = 1;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("1 min total • background less than a minute\nfrom last full charge");
+ }
+
+ @Test
+ public void testInitHeader_TotalAMinBackgroundZeroAndGraphDisabled_hasCorrectSummary() {
+ when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+ .thenReturn(false);
+ final long backgroundTimeZero = 0;
+ final long foregroundTimeAMinutes = 60000;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeAMinutes);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.initHeader();
+
+ ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("1 min total from last full charge");
+ }
+
+ @Test
+ public void testInitHeader_fgTwoMinBgFourMinAndGraphDisabled_hasCorrectSummary() {
+ when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+ .thenReturn(false);
+ final long backgroundTimeFourMinute = 240000;
+ final long foregroundTimeTwoMinutes = 120000;
+ Bundle bundle = new Bundle(2);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeFourMinute);
+ bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes);
+ when(mFragment.getArguments()).thenReturn(bundle);
+ mFragment.initHeader();
+
+ ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(mEntityHeaderController).setSummary(captor.capture());
+ assertThat(captor.getValue().toString())
+ .isEqualTo("6 min total • 4 min background\nfrom last full charge");
+ }
+
+ @Test
public void testInitHeader_noUsageTime_hasCorrectSummary() {
Bundle bundle = new Bundle(2);
bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, /* value */ 0);
@@ -352,7 +493,7 @@
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
verify(mEntityHeaderController).setSummary(captor.capture());
assertThat(captor.getValue().toString())
- .isEqualTo("1 min total • background less than a minute for past 24 hr");
+ .isEqualTo("1 min total • background less than a minute\nfor past 24 hr");
}
@Test
@@ -385,7 +526,7 @@
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
verify(mEntityHeaderController).setSummary(captor.capture());
assertThat(captor.getValue().toString())
- .isEqualTo("6 min total • 4 min background for past 24 hr");
+ .isEqualTo("6 min total • 4 min background\nfor past 24 hr");
}
@Test
@@ -423,7 +564,7 @@
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
verify(mEntityHeaderController).setSummary(captor.capture());
assertThat(captor.getValue().toString())
- .isEqualTo("1 min total • background less than a minute for 12 am-2 am");
+ .isEqualTo("1 min total • background less than a minute\nfor 12 am-2 am");
}
@Test
@@ -458,7 +599,7 @@
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
verify(mEntityHeaderController).setSummary(captor.capture());
assertThat(captor.getValue().toString())
- .isEqualTo("6 min total • 4 min background for 12 am-2 am");
+ .isEqualTo("6 min total • 4 min background\nfor 12 am-2 am");
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
new file mode 100644
index 0000000..877ebc2
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2021 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.fuelgauge;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.Context;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.settings.testutils.FakeFeatureFactory;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+
+@RunWith(RobolectricTestRunner.class)
+public final class BatteryChartViewTest {
+
+ private Context mContext;
+ private BatteryChartView mBatteryChartView;
+ private FakeFeatureFactory mFeatureFactory;
+ private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
+
+ @Mock private AccessibilityServiceInfo mockAccessibilityServiceInfo;
+ @Mock private AccessibilityManager mockAccessibilityManager;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
+ mPowerUsageFeatureProvider = mFeatureFactory.powerUsageFeatureProvider;
+ mContext = spy(RuntimeEnvironment.application);
+ mBatteryChartView = new BatteryChartView(mContext);
+ doReturn(mockAccessibilityManager).when(mContext)
+ .getSystemService(AccessibilityManager.class);
+ doReturn("TalkBackService").when(mockAccessibilityServiceInfo).getId();
+ doReturn(Arrays.asList(mockAccessibilityServiceInfo))
+ .when(mockAccessibilityManager)
+ .getEnabledAccessibilityServiceList(anyInt());
+ }
+
+ @Test
+ public void testIsAccessibilityEnabled_disable_returnFalse() {
+ doReturn(false).when(mockAccessibilityManager).isEnabled();
+ assertThat(BatteryChartView.isAccessibilityEnabled(mContext)).isFalse();
+ }
+
+ @Test
+ public void testIsAccessibilityEnabled_emptyInfo_returnFalse() {
+ doReturn(true).when(mockAccessibilityManager).isEnabled();
+ doReturn(new ArrayList<AccessibilityServiceInfo>())
+ .when(mockAccessibilityManager)
+ .getEnabledAccessibilityServiceList(anyInt());
+
+ assertThat(BatteryChartView.isAccessibilityEnabled(mContext)).isFalse();
+ }
+
+ @Test
+ public void testIsAccessibilityEnabled_validServiceId_returnTrue() {
+ doReturn(true).when(mockAccessibilityManager).isEnabled();
+ assertThat(BatteryChartView.isAccessibilityEnabled(mContext)).isTrue();
+ }
+
+ @Test
+ public void testSetSelectedIndex_invokesCallback() {
+ final int selectedIndex[] = new int[1];
+ final int expectedIndex = 2;
+ mBatteryChartView.mSelectedIndex = 1;
+ mBatteryChartView.setOnSelectListener(
+ trapezoidIndex -> {
+ selectedIndex[0] = trapezoidIndex;
+ });
+
+ mBatteryChartView.setSelectedIndex(expectedIndex);
+
+ assertThat(mBatteryChartView.mSelectedIndex)
+ .isEqualTo(expectedIndex);
+ assertThat(selectedIndex[0]).isEqualTo(expectedIndex);
+ }
+
+ @Test
+ public void testSetSelectedIndex_sameIndex_notInvokesCallback() {
+ final int selectedIndex[] = new int[1];
+ final int expectedIndex = 1;
+ mBatteryChartView.mSelectedIndex = expectedIndex;
+ mBatteryChartView.setOnSelectListener(
+ trapezoidIndex -> {
+ selectedIndex[0] = trapezoidIndex;
+ });
+
+ mBatteryChartView.setSelectedIndex(expectedIndex);
+
+ assertThat(selectedIndex[0]).isNotEqualTo(expectedIndex);
+ }
+
+ @Test
+ public void testClickable_isChartGraphSlotsEnabledIsFalse_notClickable() {
+ mBatteryChartView.setClickableForce(true);
+ when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
+ .thenReturn(false);
+
+ mBatteryChartView.onAttachedToWindow();
+ assertThat(mBatteryChartView.isClickable()).isFalse();
+ }
+
+ @Test
+ public void testClickable_accessibilityIsDisabled_clickable() {
+ mBatteryChartView.setClickableForce(true);
+ when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
+ .thenReturn(true);
+ doReturn(false).when(mockAccessibilityManager).isEnabled();
+
+ mBatteryChartView.onAttachedToWindow();
+ assertThat(mBatteryChartView.isClickable()).isTrue();
+ }
+
+ @Test
+ public void testClickable_accessibilityIsEnabledWithoutValidId_clickable() {
+ mBatteryChartView.setClickableForce(true);
+ when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
+ .thenReturn(true);
+ doReturn(true).when(mockAccessibilityManager).isEnabled();
+ doReturn(new ArrayList<AccessibilityServiceInfo>())
+ .when(mockAccessibilityManager)
+ .getEnabledAccessibilityServiceList(anyInt());
+
+ mBatteryChartView.onAttachedToWindow();
+ assertThat(mBatteryChartView.isClickable()).isTrue();
+ }
+
+ @Test
+ public void testClickable_accessibilityIsEnabledWithValidId_notClickable() {
+ mBatteryChartView.setClickableForce(true);
+ when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
+ .thenReturn(true);
+ doReturn(true).when(mockAccessibilityManager).isEnabled();
+
+ mBatteryChartView.onAttachedToWindow();
+ assertThat(mBatteryChartView.isClickable()).isFalse();
+ }
+}