Merge "Add BatteryFix Slice"

This commit is contained in:
Raff Tsai
2018-11-21 05:57:32 +00:00
committed by Android (Google) Code Review
9 changed files with 468 additions and 35 deletions

View File

@@ -1,18 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="4">
<issue
id="LintError"
severity="Error"
message="No `.class` files were found in project &quot;.&quot;, so none of the classfile based checks could be run. Does the project need to be built first?"
category="Lint"
priority="10"
summary="Lint Failure"
explanation="This issue type represents a problem running lint itself. Examples include failure to find bytecode for source files (which means certain detectors could not be run), parsing errors in lint configuration files, etc.&#xA;These errors are not errors in your own code, but they are shown to make it clear that some checks were not completed.">
<location
file="."/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -2553,7 +2541,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rXC/strings.xml"
line="2530"
line="2533"
column="168"/>
</issue>
@@ -2569,7 +2557,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rAU/strings.xml"
line="2531"
line="2534"
column="64"/>
</issue>
@@ -2585,7 +2573,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rCA/strings.xml"
line="2531"
line="2534"
column="64"/>
</issue>
@@ -2601,7 +2589,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rGB/strings.xml"
line="2531"
line="2534"
column="64"/>
</issue>
@@ -2617,7 +2605,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rIN/strings.xml"
line="2531"
line="2534"
column="64"/>
</issue>
@@ -2633,7 +2621,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/strings.xml"
line="5886"
line="5902"
column="36"/>
</issue>
@@ -2665,7 +2653,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
line="443"
line="448"
column="44"/>
</issue>
@@ -2681,7 +2669,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
line="449"
line="454"
column="44"/>
</issue>
@@ -2697,7 +2685,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
line="450"
line="455"
column="44"/>
</issue>
@@ -2761,7 +2749,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="91"
line="90"
column="47"/>
</issue>
@@ -2777,7 +2765,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="91"
line="90"
column="47"/>
</issue>
@@ -2793,7 +2781,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="97"
line="96"
column="40"/>
</issue>
@@ -2809,7 +2797,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="97"
line="96"
column="40"/>
</issue>
@@ -2825,7 +2813,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="160"
line="159"
column="45"/>
</issue>
@@ -2841,7 +2829,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="161"
line="160"
column="49"/>
</issue>
@@ -2857,7 +2845,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="169"
line="168"
column="45"/>
</issue>
@@ -2873,10 +2861,58 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="170"
line="169"
column="49"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item name=&quot;batteryGoodColor&quot;>@color/battery_good_color_light&lt;/item>"
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="185"
column="39"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item name=&quot;batteryMaybeColor&quot;>@color/battery_maybe_color_light&lt;/item>"
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="186"
column="40"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item name=&quot;batteryBadColor&quot;>@color/battery_bad_color_light&lt;/item>"
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="187"
column="38"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"

View File

@@ -180,6 +180,11 @@
<!-- action bar, needed for search bar icon tinting -->
<item name="android:actionBarTheme">@*android:style/ThemeOverlay.DeviceDefault.ActionBar.Accent</item>
<!-- For battery status icons in -->
<item name="batteryGoodColor">@color/battery_good_color_light</item>
<item name="batteryMaybeColor">@color/battery_maybe_color_light</item>
<item name="batteryBadColor">@color/battery_bad_color_light</item>
</style>
<style name="Theme.Settings.Home" parent="Theme.Settings.HomeBase">

View File

@@ -26,6 +26,7 @@ import androidx.annotation.IntDef;
import androidx.annotation.VisibleForTesting;
import com.android.settings.Utils;
import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -115,6 +116,6 @@ public class BatteryBroadcastReceiver extends BroadcastReceiver {
mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_SAVER);
}
}
BatteryFixSlice.updateBatteryTipAvailabilityCache(mContext);
}
}

View File

@@ -21,6 +21,7 @@ import static android.provider.SettingsSlicesContract.KEY_WIFI;
import android.annotation.Nullable;
import com.android.settings.homepage.contextualcards.deviceinfo.BatterySlice;
import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
import com.android.settings.intelligence.ContextualCardProto.ContextualCard;
@@ -61,11 +62,18 @@ public class SettingsContextualCardProvider extends ContextualCardProvider {
.setCardName(LowStorageSlice.PATH_LOW_STORAGE)
.setCardCategory(ContextualCard.Category.IMPORTANT)
.build();
final ContextualCard batteryFixCard =
ContextualCard.newBuilder()
.setSliceUri(BatteryFixSlice.BATTERY_FIX_URI.toString())
.setCardName(BatteryFixSlice.PATH_BATTERY_FIX)
.setCardCategory(ContextualCard.Category.IMPORTANT)
.build();
final ContextualCardList cards = ContextualCardList.newBuilder()
.addCard(wifiCard)
.addCard(batteryInfoCard)
.addCard(connectedDeviceCard)
.addCard(lowStorageCard)
.addCard(batteryFixCard)
.build();
return cards;

View File

@@ -0,0 +1,224 @@
/*
* Copyright (C) 2018 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.homepage.contextualcards.slices;
import static android.content.Context.MODE_PRIVATE;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.ListBuilder.RowBuilder;
import androidx.slice.builders.SliceAction;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R;
import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.fuelgauge.BatteryStatsHelperLoader;
import com.android.settings.fuelgauge.PowerUsageSummary;
import com.android.settings.fuelgauge.batterytip.BatteryTipLoader;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBackgroundWorker;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.utils.ThreadUtils;
import java.util.List;
public class BatteryFixSlice implements CustomSliceable {
/**
* Unique name of Battery Fix Slice.
*/
public static final String PATH_BATTERY_FIX = "battery_fix";
/**
* Uri for Battery Fix Slice.
*/
public static final Uri BATTERY_FIX_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(PATH_BATTERY_FIX)
.build();
@VisibleForTesting
static final String PREFS = "battery_fix_prefs";
@VisibleForTesting
static final String KEY_CURRENT_TIPS_TYPE = "current_tip_type";
private static final String TAG = "BatteryFixSlice";
private final Context mContext;
public BatteryFixSlice(Context context) {
mContext = context;
}
@Override
public Uri getUri() {
return BATTERY_FIX_URI;
}
/**
* Return a Slice bound to {@link #BATTERY_FIX_URI}.
*/
@Override
public Slice getSlice() {
IconCompat icon;
SliceAction primaryAction;
Slice slice = null;
// TipType.SUMMARY is battery good
if (readBatteryTipAvailabilityCache(mContext) == BatteryTip.TipType.SUMMARY) {
return null;
}
final List<BatteryTip> batteryTips = SliceBackgroundWorker.getInstance(mContext,
this).getResults();
if (batteryTips != null) {
for (BatteryTip batteryTip : batteryTips) {
if (batteryTip.getState() != BatteryTip.StateType.INVISIBLE) {
icon = IconCompat.createWithResource(mContext, batteryTip.getIconId());
primaryAction = new SliceAction(getPrimaryAction(),
icon,
batteryTip.getTitle(mContext));
slice = new ListBuilder(mContext, BATTERY_FIX_URI, ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.addRow(new RowBuilder()
.setTitle(batteryTip.getTitle(mContext))
.setSubtitle(batteryTip.getSummary(mContext))
.setPrimaryAction(primaryAction)
.addEndItem(icon, ListBuilder.ICON_IMAGE))
.build();
break;
}
}
} else {
icon = IconCompat.createWithResource(mContext,
R.drawable.ic_battery_status_good_24dp);
final String title = mContext.getString(R.string.power_usage_summary_title);
primaryAction = new SliceAction(getPrimaryAction(), icon, title);
slice = new ListBuilder(mContext, BATTERY_FIX_URI, ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.addRow(new RowBuilder()
.setTitle(title)
.setPrimaryAction(primaryAction)
.addEndItem(icon, ListBuilder.ICON_IMAGE))
.build();
}
return slice;
}
@Override
public Intent getIntent() {
final String screenTitle = mContext.getText(R.string.power_usage_summary_title)
.toString();
final Uri contentUri = new Uri.Builder().appendPath(PATH_BATTERY_FIX).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
PowerUsageSummary.class.getName(), PATH_BATTERY_FIX,
screenTitle,
MetricsProto.MetricsEvent.SLICE)
.setClassName(mContext.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
}
@Override
public void onNotifyChange(Intent intent) {
}
@Override
public Class getBackgroundWorkerClass() {
return BatteryTipWorker.class;
}
private PendingIntent getPrimaryAction() {
final Intent intent = getIntent();
return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */);
}
// TODO(b/114807643): we should find a better way to get current battery tip type quickly
// Now we save battery tip type to shared preference when battery level changes
public static void updateBatteryTipAvailabilityCache(Context context) {
ThreadUtils.postOnBackgroundThread(() -> {
refreshBatteryTips(context);
});
}
@VisibleForTesting
static int readBatteryTipAvailabilityCache(Context context) {
final SharedPreferences prefs = context.getSharedPreferences(PREFS, MODE_PRIVATE);
return prefs.getInt(KEY_CURRENT_TIPS_TYPE, BatteryTip.TipType.SUMMARY);
}
@WorkerThread
private static List<BatteryTip> refreshBatteryTips(Context context) {
final BatteryStatsHelperLoader statsLoader = new BatteryStatsHelperLoader(context);
final BatteryStatsHelper statsHelper = statsLoader.loadInBackground();
final BatteryTipLoader loader = new BatteryTipLoader(context, statsHelper);
final List<BatteryTip> batteryTips = loader.loadInBackground();
for (BatteryTip batteryTip : batteryTips) {
if (batteryTip.getState() != BatteryTip.StateType.INVISIBLE) {
SharedPreferences.Editor editor = context.getSharedPreferences(PREFS,
MODE_PRIVATE).edit();
editor.putInt(KEY_CURRENT_TIPS_TYPE, batteryTip.getType());
editor.apply();
break;
}
}
return batteryTips;
}
public static class BatteryTipWorker extends SliceBackgroundWorker<BatteryTip> {
private final Context mContext;
public BatteryTipWorker(Context context, Uri uri) {
super(context, uri);
mContext = context;
}
@Override
protected void onSlicePinned() {
ThreadUtils.postOnBackgroundThread(() -> {
final List<BatteryTip> batteryTips = refreshBatteryTips(mContext);
updateResults(batteryTips);
});
}
@Override
protected void onSliceUnpinned() {
}
@Override
public void close() {
}
}
}

View File

@@ -20,10 +20,13 @@ import android.content.Context;
import android.net.Uri;
import android.util.ArrayMap;
import androidx.annotation.VisibleForTesting;
import com.android.settings.homepage.contextualcards.deviceinfo.BatterySlice;
import com.android.settings.homepage.contextualcards.deviceinfo.DataUsageSlice;
import com.android.settings.homepage.contextualcards.deviceinfo.DeviceInfoSlice;
import com.android.settings.homepage.contextualcards.deviceinfo.StorageSlice;
import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
import com.android.settings.wifi.WifiSlice;
@@ -34,13 +37,11 @@ import java.util.WeakHashMap;
/**
* Manages custom {@link androidx.slice.Slice Slices}, which are all Slices not backed by
* preferences.
* <p>
* By default, all Slices in Settings should be built by a
* </p>
*/
public class CustomSliceManager {
protected final Map<Uri, Class<? extends CustomSliceable>> mUriMap;
@VisibleForTesting
final Map<Uri, Class<? extends CustomSliceable>> mUriMap;
private final Context mContext;
private final Map<Uri, CustomSliceable> mSliceableCache;
@@ -107,5 +108,6 @@ public class CustomSliceManager {
mUriMap.put(BatterySlice.BATTERY_CARD_URI, BatterySlice.class);
mUriMap.put(ConnectedDeviceSlice.CONNECTED_DEVICE_URI, ConnectedDeviceSlice.class);
mUriMap.put(LowStorageSlice.LOW_STORAGE_URI, LowStorageSlice.class);
mUriMap.put(BatteryFixSlice.BATTERY_FIX_URI, BatteryFixSlice.class);
}
}

View File

@@ -40,6 +40,7 @@ import android.os.Bundle;
import android.widget.ImageView;
import com.android.settings.homepage.SettingsHomepageActivity;
import com.android.settings.homepage.contextualcards.slices.BatteryFixSliceTest;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
@@ -99,7 +100,11 @@ public class AvatarViewMixinTest {
}
@Test
@Config(qualifiers = "mcc999")
@Config(qualifiers = "mcc999",
shadows = {
BatteryFixSliceTest.ShadowBatteryStatsHelperLoader.class,
BatteryFixSliceTest.ShadowBatteryTipLoader.class
})
public void onStart_useMockAvatarViewMixin_shouldBeExecuted() {
final AvatarViewMixin mockAvatar = spy(new AvatarViewMixin(mActivity, mImageView));

View File

@@ -33,6 +33,7 @@ import android.os.BatteryManager;
import android.os.PowerManager;
import com.android.settings.Utils;
import com.android.settings.homepage.contextualcards.slices.BatteryFixSliceTest;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
@@ -42,6 +43,11 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
@RunWith(SettingsRobolectricTestRunner.class)
public class BatteryBroadcastReceiverTest {
@@ -74,6 +80,10 @@ public class BatteryBroadcastReceiverTest {
}
@Test
@Config(shadows = {
BatteryFixSliceTest.ShadowBatteryStatsHelperLoader.class,
BatteryFixSliceTest.ShadowBatteryTipLoader.class
})
public void testOnReceive_batteryLevelChanged_dataUpdated() {
mBatteryBroadcastReceiver.onReceive(mContext, mChargingIntent);
@@ -85,6 +95,10 @@ public class BatteryBroadcastReceiverTest {
}
@Test
@Config(shadows = {
BatteryFixSliceTest.ShadowBatteryStatsHelperLoader.class,
BatteryFixSliceTest.ShadowBatteryTipLoader.class
})
public void testOnReceive_powerSaveModeChanged_listenerInvoked() {
mBatteryBroadcastReceiver.onReceive(mContext,
new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
@@ -93,6 +107,10 @@ public class BatteryBroadcastReceiverTest {
}
@Test
@Config(shadows = {
BatteryFixSliceTest.ShadowBatteryStatsHelperLoader.class,
BatteryFixSliceTest.ShadowBatteryTipLoader.class
})
public void testOnReceive_batteryDataNotChanged_listenerNotInvoked() {
final String batteryLevel = Utils.getBatteryPercentage(mChargingIntent);
final String batteryStatus =
@@ -108,6 +126,10 @@ public class BatteryBroadcastReceiverTest {
}
@Test
@Config(shadows = {
BatteryFixSliceTest.ShadowBatteryStatsHelperLoader.class,
BatteryFixSliceTest.ShadowBatteryTipLoader.class
})
public void testRegister_updateBatteryStatus() {
doReturn(mChargingIntent).when(mContext).registerReceiver(any(), any());

View File

@@ -0,0 +1,130 @@
/*
* Copyright (C) 2018 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.homepage.contextualcards.slices;
import static android.content.Context.MODE_PRIVATE;
import static com.android.settings.homepage.contextualcards.slices.BatteryFixSlice.KEY_CURRENT_TIPS_TYPE;
import static com.android.settings.homepage.contextualcards.slices.BatteryFixSlice.PREFS;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.content.SharedPreferences;
import androidx.slice.SliceProvider;
import androidx.slice.widget.SliceLiveData;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.fuelgauge.BatteryStatsHelperLoader;
import com.android.settings.fuelgauge.batterytip.BatteryTipLoader;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.EarlyWarningTip;
import com.android.settings.fuelgauge.batterytip.tips.LowBatteryTip;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
import java.util.ArrayList;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
public class BatteryFixSliceTest {
private Context mContext;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
// Set-up specs for SliceMetadata.
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
}
@After
public void tearDown() {
ShadowBatteryTipLoader.reset();
}
@Test
public void readBatteryTipfromPref_readCorrectValue() {
int target = 111;
final SharedPreferences.Editor editor = mContext.getSharedPreferences(PREFS,
MODE_PRIVATE).edit();
editor.putInt(KEY_CURRENT_TIPS_TYPE, target);
editor.commit();
assertThat(BatteryFixSlice.readBatteryTipAvailabilityCache(mContext)).isEqualTo(target);
}
@Test
@Config(shadows = {
ShadowBatteryStatsHelperLoader.class,
ShadowBatteryTipLoader.class
})
public void updateBatteryTipAvailabilityCache_writeCorrectValue() {
final List<BatteryTip> tips = new ArrayList<>();
tips.add(new LowBatteryTip(BatteryTip.StateType.INVISIBLE, false, ""));
tips.add(new EarlyWarningTip(BatteryTip.StateType.HANDLED, false));
ShadowBatteryTipLoader.setBatteryTips(tips);
BatteryFixSlice.updateBatteryTipAvailabilityCache(mContext);
assertThat(BatteryFixSlice.readBatteryTipAvailabilityCache(mContext)).isEqualTo(
BatteryTip.TipType.BATTERY_SAVER);
}
@Implements(BatteryStatsHelperLoader.class)
public static class ShadowBatteryStatsHelperLoader {
@Implementation
protected BatteryStatsHelper loadInBackground() {
return null;
}
}
@Implements(BatteryTipLoader.class)
public static class ShadowBatteryTipLoader {
private static List<BatteryTip> sBatteryTips = new ArrayList<>();
@Resetter
public static void reset() {
sBatteryTips = new ArrayList<>();
}
@Implementation
protected List<BatteryTip> loadInBackground() {
return sBatteryTips;
}
public static void setBatteryTips(List<BatteryTip> tips) {
sBatteryTips = tips;
}
}
}