Add BatteryMeterView in Settings

1. Show gauge icon at the top of battery main page instead of
battery usage graph.
2. Move the click action from battery usage graph to gauge icon.

Bug: 34387464
Test: RunSettingsRoboTest

Change-Id: Ib182619d6805b401cde03a50e2ae907cf4df7b94
This commit is contained in:
jackqdyulei
2017-02-02 11:25:15 -08:00
parent 3fca717d3b
commit 51967c0e6a
15 changed files with 366 additions and 38 deletions

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/app_snippet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:orientation="horizontal"
android:paddingTop="24dp"
android:paddingBottom="24dp"
style="@style/EntityHeader">
<com.android.settings.fuelgauge.BatteryMeterView
android:id="@+id/battery_header_icon"
android:layout_width="@dimen/battery_meter_width"
android:layout_height="@dimen/battery_meter_height"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:orientation="vertical">
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:gravity="center"
android:textAppearance="@android:style/TextAppearance.Material.Medium"/>
<TextView
android:id="@+id/summary1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:gravity="center"
android:textAppearance="@android:style/TextAppearance.Material.Small"
android:text="@string/estimated_time_left"/>
<TextView
android:id="@+id/summary2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:gravity="center"
android:textAppearance="@android:style/TextAppearance.Material.Small"
android:text="@string/estimated_time_description"/>
</LinearLayout>
</LinearLayout>

View File

@@ -311,4 +311,8 @@
<!-- Padding between the donut and the storage summary. --> <!-- Padding between the donut and the storage summary. -->
<dimen name="storage_summary_padding_end">16dp</dimen> <dimen name="storage_summary_padding_end">16dp</dimen>
<!-- Battery meter view size -->
<dimen name="battery_meter_width">66dp</dimen>
<dimen name="battery_meter_height">100dp</dimen>
</resources> </resources>

View File

@@ -4478,6 +4478,12 @@
<!-- Description for battery usage detail information since last full charge. [CHAR LIMIT=120] --> <!-- Description for battery usage detail information since last full charge. [CHAR LIMIT=120] -->
<string name="battery_detail_since_full_charge">Usage breakdown since last full charge</string> <string name="battery_detail_since_full_charge">Usage breakdown since last full charge</string>
<!-- Description for battery time left, i.e. 50min Estimated time left. [CHAR LIMIT=80]-->
<string name="estimated_time_left">Estimated time left</string>
<!-- Description for estimated time. [CHAR LIMIT=80]-->
<string name="estimated_time_description">Estimation may change based on usage</string>
<!-- Menu label for viewing battery usage since unplugged --> <!-- Menu label for viewing battery usage since unplugged -->
<string name="menu_stats_unplugged"><xliff:g id="unplugged">%1$s</xliff:g> since unplugged</string> <string name="menu_stats_unplugged"><xliff:g id="unplugged">%1$s</xliff:g> since unplugged</string>
<!-- Menu label for viewing battery usage since unplugged --> <!-- Menu label for viewing battery usage since unplugged -->

View File

@@ -38,6 +38,7 @@
<com.android.settings.applications.LayoutPreference <com.android.settings.applications.LayoutPreference
android:key="remove_account" android:key="remove_account"
android:layout="@layout/remove_account_button" android:layout="@layout/remove_account_button"
android:order="100" /> android:order="100"
android:selectable="false"/>
</PreferenceScreen> </PreferenceScreen>

View File

@@ -30,6 +30,7 @@
<com.android.settings.applications.LayoutPreference <com.android.settings.applications.LayoutPreference
android:key="change_storage_button" android:key="change_storage_button"
android:selectable="false"
android:layout="@layout/single_button_panel" /> android:layout="@layout/single_button_panel" />
<PreferenceCategory <PreferenceCategory
@@ -69,6 +70,7 @@
<com.android.settings.applications.LayoutPreference <com.android.settings.applications.LayoutPreference
android:key="clear_data_button" android:key="clear_data_button"
android:selectable="false"
android:layout="@layout/single_button_panel" /> android:layout="@layout/single_button_panel" />
</PreferenceCategory> </PreferenceCategory>

View File

@@ -20,8 +20,10 @@
android:title="@string/power_usage_summary_title" android:title="@string/power_usage_summary_title"
settings:keywords="@string/keywords_battery"> settings:keywords="@string/keywords_battery">
<com.android.settings.fuelgauge.BatteryHistoryPreference <com.android.settings.applications.LayoutPreference
android:key="battery_history"/> android:key="battery_header"
android:selectable="true"
android:layout="@layout/battery_header"/>
<PreferenceCategory <PreferenceCategory
android:key="power_management" android:key="power_management"

View File

@@ -59,7 +59,6 @@ public class LayoutPreference extends Preference {
private void setView(View view) { private void setView(View view) {
setLayoutResource(R.layout.layout_preference_frame); setLayoutResource(R.layout.layout_preference_frame);
setSelectable(false);
final ViewGroup allDetails = (ViewGroup) view.findViewById(R.id.all_details); final ViewGroup allDetails = (ViewGroup) view.findViewById(R.id.all_details);
if (allDetails != null) { if (allDetails != null) {
Utils.forceCustomPadding(allDetails, true /* additive padding */); Utils.forceCustomPadding(allDetails, true /* additive padding */);
@@ -70,6 +69,7 @@ public class LayoutPreference extends Preference {
@Override @Override
public void onBindViewHolder(PreferenceViewHolder view) { public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
FrameLayout layout = (FrameLayout) view.itemView; FrameLayout layout = (FrameLayout) view.itemView;
layout.removeAllViews(); layout.removeAllViews();
ViewGroup parent = (ViewGroup) mRootView.getParent(); ViewGroup parent = (ViewGroup) mRootView.getParent();

View File

@@ -37,6 +37,7 @@ import com.android.settingslib.graph.UsageView;
public class BatteryHistoryDetail extends SettingsPreferenceFragment { public class BatteryHistoryDetail extends SettingsPreferenceFragment {
public static final String EXTRA_STATS = "stats"; public static final String EXTRA_STATS = "stats";
public static final String EXTRA_BROADCAST = "broadcast"; public static final String EXTRA_BROADCAST = "broadcast";
public static final String BATTERY_HISTORY_FILE = "tmp_bat_history.bin";
private BatteryStats mStats; private BatteryStats mStats;
private Intent mBatteryBroadcast; private Intent mBatteryBroadcast;

View File

@@ -33,43 +33,18 @@ import com.android.settingslib.graph.UsageView;
/** /**
* Custom preference for displaying power consumption as a bar and an icon on the left for the * Custom preference for displaying power consumption as a bar and an icon on the left for the
* subsystem/app type. * subsystem/app type.
*
*/ */
public class BatteryHistoryPreference extends Preference { public class BatteryHistoryPreference extends Preference {
protected static final String BATTERY_HISTORY_FILE = "tmp_bat_history.bin";
private BatteryStatsHelper mHelper;
private BatteryInfo mBatteryInfo; private BatteryInfo mBatteryInfo;
public BatteryHistoryPreference(Context context, AttributeSet attrs) { public BatteryHistoryPreference(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
setLayoutResource(R.layout.battery_usage_graph); setLayoutResource(R.layout.battery_usage_graph);
setSelectable(true); setSelectable(false);
}
@Override
public void performClick() {
// TODO(b/34890746): remove this since history graph is not clickable
final Context context = getContext();
final PowerUsageFeatureProvider featureProvider = FeatureFactory.getFactory(context)
.getPowerUsageFeatureProvider(context);
if (featureProvider.isAdvancedUiEnabled()) {
Utils.startWithFragment(getContext(), PowerUsageAdvanced.class.getName(), null,
null, 0, R.string.advanced_battery_title, null);
} else {
mHelper.storeStatsHistoryInFile(BATTERY_HISTORY_FILE);
Bundle args = new Bundle();
args.putString(BatteryHistoryDetail.EXTRA_STATS, BATTERY_HISTORY_FILE);
args.putParcelable(BatteryHistoryDetail.EXTRA_BROADCAST, mHelper.getBatteryBroadcast());
Utils.startWithFragment(getContext(), BatteryHistoryDetail.class.getName(), args,
null, 0, R.string.history_details_title, null);
}
} }
public void setStats(BatteryStatsHelper batteryStats) { public void setStats(BatteryStatsHelper batteryStats) {
mHelper = batteryStats;
final long elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000; final long elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000;
mBatteryInfo = BatteryInfo.getBatteryInfo(getContext(), batteryStats.getBatteryBroadcast(), mBatteryInfo = BatteryInfo.getBatteryInfo(getContext(), batteryStats.getBatteryBroadcast(),
batteryStats.getStats(), elapsedRealtimeUs); batteryStats.getStats(), elapsedRealtimeUs);

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2017 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 android.annotation.Nullable;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.support.annotation.VisibleForTesting;
import android.util.AttributeSet;
import android.widget.ImageView;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.graph.BatteryMeterDrawableBase;
public class BatteryMeterView extends ImageView {
private BatteryMeterDrawable mDrawable;
public BatteryMeterView(Context context) {
this(context, null, 0);
}
public BatteryMeterView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public BatteryMeterView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
final int frameColor = context.getColor(R.color.batterymeter_frame_color);
final int tintColor = Utils.getColorAttr(context, android.R.attr.colorAccent);
mDrawable = new BatteryMeterDrawable(context, frameColor);
mDrawable.setColorFilter(new PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN));
mDrawable.setShowPercent(true);
setImageDrawable(mDrawable);
}
public void setBatteryInfo(int level) {
mDrawable.setBatteryLevel(level);
}
@VisibleForTesting
void setBatteryDrawable(BatteryMeterDrawable drawable) {
mDrawable = drawable;
}
public static class BatteryMeterDrawable extends BatteryMeterDrawableBase {
private final int mIntrinsicWidth;
private final int mIntrinsicHeight;
public BatteryMeterDrawable(Context context, int frameColor) {
super(context, frameColor);
mIntrinsicWidth = context.getResources()
.getDimensionPixelSize(R.dimen.battery_meter_width);
mIntrinsicHeight = context.getResources()
.getDimensionPixelSize(R.dimen.battery_meter_height);
}
@Override
public int getIntrinsicWidth() {
return mIntrinsicWidth;
}
@Override
public int getIntrinsicHeight() {
return mIntrinsicHeight;
}
}
}

View File

@@ -72,7 +72,7 @@ public abstract class PowerUsageBase extends DashboardFragment {
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
BatteryStatsHelper.dropFile(getActivity(), BatteryHistoryPreference.BATTERY_HISTORY_FILE); BatteryStatsHelper.dropFile(getActivity(), BatteryHistoryDetail.BATTERY_HISTORY_FILE);
updateBatteryStatus(getActivity().registerReceiver(mBatteryInfoReceiver, updateBatteryStatus(getActivity().registerReceiver(mBatteryInfoReceiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED))); new IntentFilter(Intent.ACTION_BATTERY_CHANGED)));
if (mHandler.hasMessages(MSG_REFRESH_STATS)) { if (mHandler.hasMessages(MSG_REFRESH_STATS)) {

View File

@@ -38,7 +38,9 @@ import android.util.TypedValue;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.BatterySipper; import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatterySipper.DrainType; import com.android.internal.os.BatterySipper.DrainType;
@@ -47,6 +49,7 @@ import com.android.settings.R;
import com.android.settings.Settings.HighPowerApplicationsActivity; import com.android.settings.Settings.HighPowerApplicationsActivity;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.applications.ManageApplications; import com.android.settings.applications.ManageApplications;
import com.android.settings.core.PreferenceController; import com.android.settings.core.PreferenceController;
import com.android.settings.dashboard.SummaryLoader; import com.android.settings.dashboard.SummaryLoader;
@@ -75,7 +78,7 @@ public class PowerUsageSummary extends PowerUsageBase {
static final String TAG = "PowerUsageSummary"; static final String TAG = "PowerUsageSummary";
private static final String KEY_APP_LIST = "app_list"; private static final String KEY_APP_LIST = "app_list";
private static final String KEY_BATTERY_HISTORY = "battery_history"; private static final String KEY_BATTERY_HEADER = "battery_header";
private static final int MENU_STATS_TYPE = Menu.FIRST; private static final int MENU_STATS_TYPE = Menu.FIRST;
private static final int MENU_HIGH_POWER_APPS = Menu.FIRST + 3; private static final int MENU_HIGH_POWER_APPS = Menu.FIRST + 3;
@@ -83,7 +86,7 @@ public class PowerUsageSummary extends PowerUsageBase {
static final int MENU_ADDITIONAL_BATTERY_INFO = Menu.FIRST + 4; static final int MENU_ADDITIONAL_BATTERY_INFO = Menu.FIRST + 4;
private static final int MENU_HELP = Menu.FIRST + 5; private static final int MENU_HELP = Menu.FIRST + 5;
private BatteryHistoryPreference mHistPref; private LayoutPreference mBatteryLayoutPref;
private PreferenceGroup mAppListGroup; private PreferenceGroup mAppListGroup;
private int mStatsType = BatteryStats.STATS_SINCE_CHARGED; private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
@@ -98,7 +101,7 @@ public class PowerUsageSummary extends PowerUsageBase {
super.onCreate(icicle); super.onCreate(icicle);
setAnimationAllowed(true); setAnimationAllowed(true);
mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_HISTORY); mBatteryLayoutPref = (LayoutPreference) findPreference(KEY_BATTERY_HEADER);
mAppListGroup = (PreferenceGroup) findPreference(KEY_APP_LIST); mAppListGroup = (PreferenceGroup) findPreference(KEY_APP_LIST);
} }
@@ -130,7 +133,10 @@ public class PowerUsageSummary extends PowerUsageBase {
@Override @Override
public boolean onPreferenceTreeClick(Preference preference) { public boolean onPreferenceTreeClick(Preference preference) {
if (!(preference instanceof PowerGaugePreference)) { if (KEY_BATTERY_HEADER.equals(preference.getKey())) {
performBatteryHeaderClick();
return true;
} else if (!(preference instanceof PowerGaugePreference)) {
return super.onPreferenceTreeClick(preference); return super.onPreferenceTreeClick(preference);
} }
PowerGaugePreference pgp = (PowerGaugePreference) preference; PowerGaugePreference pgp = (PowerGaugePreference) preference;
@@ -224,6 +230,26 @@ public class PowerUsageSummary extends PowerUsageBase {
} }
} }
private void performBatteryHeaderClick() {
final Context context = getContext();
final PowerUsageFeatureProvider featureProvider = FeatureFactory.getFactory(context)
.getPowerUsageFeatureProvider(context);
if (featureProvider.isAdvancedUiEnabled()) {
Utils.startWithFragment(getContext(), PowerUsageAdvanced.class.getName(), null,
null, 0, R.string.advanced_battery_title, null);
} else {
mStatsHelper.storeStatsHistoryInFile(BatteryHistoryDetail.BATTERY_HISTORY_FILE);
Bundle args = new Bundle(2);
args.putString(BatteryHistoryDetail.EXTRA_STATS,
BatteryHistoryDetail.BATTERY_HISTORY_FILE);
args.putParcelable(BatteryHistoryDetail.EXTRA_BROADCAST,
mStatsHelper.getBatteryBroadcast());
Utils.startWithFragment(getContext(), BatteryHistoryDetail.class.getName(), args,
null, 0, R.string.history_details_title, null);
}
}
private static boolean isSharedGid(int uid) { private static boolean isSharedGid(int uid) {
return UserHandle.getAppIdFromSharedAppGid(uid) > 0; return UserHandle.getAppIdFromSharedAppGid(uid) > 0;
} }
@@ -325,7 +351,14 @@ public class PowerUsageSummary extends PowerUsageBase {
protected void refreshStats() { protected void refreshStats() {
super.refreshStats(); super.refreshStats();
updatePreference(mHistPref);
BatteryInfo.getBatteryInfo(getContext(), new BatteryInfo.Callback() {
@Override
public void onBatteryInfoLoaded(BatteryInfo info) {
updateHeaderPreference(info);
}
});
cacheRemoveAllPrefs(mAppListGroup); cacheRemoveAllPrefs(mAppListGroup);
mAppListGroup.setOrderingAsAdded(false); mAppListGroup.setOrderingAsAdded(false);
boolean addedSome = false; boolean addedSome = false;
@@ -436,6 +469,27 @@ public class PowerUsageSummary extends PowerUsageBase {
BatteryEntry.startRequestQueue(); BatteryEntry.startRequestQueue();
} }
@VisibleForTesting
void updateHeaderPreference(BatteryInfo info) {
final BatteryMeterView batteryView = (BatteryMeterView) mBatteryLayoutPref
.findViewById(R.id.battery_header_icon);
final TextView timeText = (TextView) mBatteryLayoutPref.findViewById(R.id.time);
final TextView summary1 = (TextView) mBatteryLayoutPref.findViewById(R.id.summary1);
final TextView summary2 = (TextView) mBatteryLayoutPref.findViewById(R.id.summary2);
final int visible = info.mBatteryLevel != 100 ? View.VISIBLE : View.INVISIBLE;
if (info.remainingTimeUs != 0) {
timeText.setText(Utils.formatElapsedTime(getContext(),
info.remainingTimeUs / 1000, false));
} else {
timeText.setText(info.remainingLabel != null ?
info.remainingLabel : info.batteryPercentString);
}
summary1.setVisibility(visible);
summary2.setVisibility(visible);
batteryView.setBatteryInfo(info.mBatteryLevel);
}
@VisibleForTesting @VisibleForTesting
void setUsageSummary(Preference preference, String usedTimePrefix, long usageTimeMs) { void setUsageSummary(Preference preference, String usedTimePrefix, long usageTimeMs) {
// Only show summary when usage time is longer than one minute // Only show summary when usage time is longer than one minute
@@ -482,6 +536,11 @@ public class PowerUsageSummary extends PowerUsageBase {
return 0; return 0;
} }
@VisibleForTesting
void setBatteryLayoutPreference(LayoutPreference layoutPreference) {
mBatteryLayoutPref = layoutPreference;
}
private static List<BatterySipper> getFakeStats() { private static List<BatterySipper> getFakeStats() {
ArrayList<BatterySipper> stats = new ArrayList<>(); ArrayList<BatterySipper> stats = new ArrayList<>();
float use = 5; float use = 5;

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2017 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 android.content.Context;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.testutils.shadow.SettingsShadowResources.SettingsShadowTheme;
import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import static org.mockito.Mockito.verify;
@RunWith(SettingsRobolectricTestRunner.class)
// TODO: Consider making the shadow class set global using a robolectric.properties file.
@Config(manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
shadows = {
SettingsShadowResources.class,
SettingsShadowTheme.class,
ShadowDynamicIndexableContentMonitor.class
})
public class BatteryMeterViewTest {
private static final int BATTERY_LEVEL = 100;
@Mock
private BatteryMeterView.BatteryMeterDrawable mDrawable;
private Context mContext;
private BatteryMeterView mBatteryMeterView;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mBatteryMeterView = new BatteryMeterView(mContext);
mBatteryMeterView.setBatteryDrawable(mDrawable);
}
@Test
public void testSetBatteryInfo_SetCorrectly() {
mBatteryMeterView.setBatteryInfo(BATTERY_LEVEL);
verify(mDrawable).setBatteryLevel(BATTERY_LEVEL);
}
}

View File

@@ -23,11 +23,15 @@ import android.text.format.DateUtils;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import com.android.internal.os.BatterySipper; import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.BatteryStatsImpl;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.TestConfig; import com.android.settings.TestConfig;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.BatteryInfo;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -36,6 +40,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -44,7 +49,6 @@ import static com.android.settings.fuelgauge.PowerUsageBase.MENU_STATS_REFRESH;
import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_ADDITIONAL_BATTERY_INFO; import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_ADDITIONAL_BATTERY_INFO;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -58,8 +62,11 @@ import static org.mockito.Mockito.when;
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class PowerUsageSummaryTest { public class PowerUsageSummaryTest {
private static final String[] PACKAGE_NAMES = {"com.app1", "com.app2"}; private static final String[] PACKAGE_NAMES = {"com.app1", "com.app2"};
private static final String TIME_LEFT = "2h30min";
private static final int UID = 123; private static final int UID = 123;
private static final int POWER_MAH = 100; private static final int POWER_MAH = 100;
private static final int BATTERY_LEVEL_FULL = 100;
private static final int BATTERY_LEVEL_HALF = 50;
private static final double BATTERY_SCREEN_USAGE = 300; private static final double BATTERY_SCREEN_USAGE = 300;
private static final double PRECISION = 0.001; private static final double PRECISION = 0.001;
private static final Intent ADDITIONAL_BATTERY_INFO_INTENT = private static final Intent ADDITIONAL_BATTERY_INFO_INTENT =
@@ -81,6 +88,18 @@ public class PowerUsageSummaryTest {
private BatterySipper mScreenBatterySipper; private BatterySipper mScreenBatterySipper;
@Mock @Mock
private PowerGaugePreference mPreference; private PowerGaugePreference mPreference;
@Mock
private LayoutPreference mBatteryLayoutPref;
@Mock
private BatteryMeterView mBatteryMeterView;
@Mock
private TextView mTimeText;
@Mock
private TextView mSummary1;
@Mock
private TextView mSummary2;
@Mock
private BatteryInfo mBatteryInfo;
private TestFragment mFragment; private TestFragment mFragment;
private FakeFeatureFactory mFeatureFactory; private FakeFeatureFactory mFeatureFactory;
@@ -111,6 +130,12 @@ public class PowerUsageSummaryTest {
when(mNormalBatterySipper.getPackages()).thenReturn(PACKAGE_NAMES); when(mNormalBatterySipper.getPackages()).thenReturn(PACKAGE_NAMES);
when(mNormalBatterySipper.getUid()).thenReturn(UID); when(mNormalBatterySipper.getUid()).thenReturn(UID);
mNormalBatterySipper.totalPowerMah = POWER_MAH; mNormalBatterySipper.totalPowerMah = POWER_MAH;
when(mBatteryLayoutPref.findViewById(R.id.summary1)).thenReturn(mSummary1);
when(mBatteryLayoutPref.findViewById(R.id.summary2)).thenReturn(mSummary2);
when(mBatteryLayoutPref.findViewById(R.id.time)).thenReturn(mTimeText);
when(mBatteryLayoutPref.findViewById(R.id.battery_header_icon))
.thenReturn(mBatteryMeterView);
mPowerUsageSummary.setBatteryLayoutPreference(mBatteryLayoutPref);
mScreenBatterySipper.drainType = BatterySipper.DrainType.SCREEN; mScreenBatterySipper.drainType = BatterySipper.DrainType.SCREEN;
mScreenBatterySipper.totalPowerMah = BATTERY_SCREEN_USAGE; mScreenBatterySipper.totalPowerMah = BATTERY_SCREEN_USAGE;
@@ -230,6 +255,28 @@ public class PowerUsageSummaryTest {
verify(mPreference).setSummary(anyString()); verify(mPreference).setSummary(anyString());
} }
@Test
public void testUpdatePreference_BatteryFull_DoNotShowSummary() {
mBatteryInfo.mBatteryLevel = BATTERY_LEVEL_FULL;
mBatteryInfo.remainingLabel = TIME_LEFT;
mPowerUsageSummary.updateHeaderPreference(mBatteryInfo);
verify(mSummary1).setVisibility(View.INVISIBLE);
verify(mSummary2).setVisibility(View.INVISIBLE);
verify(mTimeText).setText(mBatteryInfo.remainingLabel);
}
@Test
public void testUpdatePreference_BatteryNotFull_ShowSummary() {
mBatteryInfo.mBatteryLevel = BATTERY_LEVEL_HALF;
mBatteryInfo.remainingLabel = TIME_LEFT;
mPowerUsageSummary.updateHeaderPreference(mBatteryInfo);
verify(mSummary1).setVisibility(View.VISIBLE);
verify(mSummary2).setVisibility(View.VISIBLE);
verify(mTimeText).setText(mBatteryInfo.remainingLabel);
}
public static class TestFragment extends PowerUsageSummary { public static class TestFragment extends PowerUsageSummary {
private Context mContext; private Context mContext;

View File

@@ -7,6 +7,7 @@ import android.content.res.Resources.Theme;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.support.annotation.ArrayRes;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.TypedValue; import android.util.TypedValue;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
@@ -59,6 +60,16 @@ public class SettingsShadowResources extends ShadowResources {
return super.loadDrawable(value, id, theme); return super.loadDrawable(value, id, theme);
} }
@Implementation
public int[] getIntArray(@ArrayRes int id) throws NotFoundException {
// The Robolectric isn't aware of resources in settingslib, so we need to stub it here
if (id == com.android.settings.R.array.batterymeter_bolt_points
|| id == com.android.settings.R.array.batterymeter_plus_points) {
return new int[2];
}
return directlyOn(realResources, Resources.class).getIntArray(id);
}
@Implements(Theme.class) @Implements(Theme.class)
public static class SettingsShadowTheme extends ShadowTheme { public static class SettingsShadowTheme extends ShadowTheme {