Create new PowerUsageAdvanced page

This page contains the graph at the top and app list at the bottom

In this cl, we reused some part of the code in PowerUsageAdvancedLegacy
to construct the graph, and also used controller to construct the app
list(So glad that we extracted it to controller before..)

Bug: 73300636
Test: RunSettingsRoboTests
Change-Id: I30afbc0327a5186f8280f5e3678330b363e2dc0d
This commit is contained in:
jackqdyulei
2018-02-27 14:30:57 -08:00
parent 5dd5a0424f
commit 319d534975
7 changed files with 327 additions and 31 deletions

View File

@@ -0,0 +1,31 @@
<?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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="power_usage_advanced_screen"
android:title="@string/advanced_battery_title"
settings:keywords="@string/keywords_battery">
<com.android.settings.fuelgauge.BatteryHistoryPreference
android:key="battery_graph"/>
<PreferenceCategory
android:key="app_list"
android:title="@string/power_usage_list_summary"/>
</PreferenceScreen>

View File

@@ -66,8 +66,4 @@
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory
android:key="app_list"
android:title="@string/power_usage_list_summary"/>
</PreferenceScreen> </PreferenceScreen>

View File

@@ -149,7 +149,7 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
@Override @Override
public boolean isAvailable() { public boolean isAvailable() {
return FeatureFlagUtils.isEnabled(mContext, FeatureFlags.BATTERY_DISPLAY_APP_LIST); return true;
} }
@Override @Override
@@ -186,12 +186,17 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
} }
} }
public void refreshAppListGroup(BatteryStatsHelper statsHelper, boolean showAllApps, public void refreshAppListGroup(BatteryStatsHelper statsHelper, boolean showAllApps) {
CharSequence timeSequence) {
if (!isAvailable()) { if (!isAvailable()) {
return; return;
} }
mBatteryStatsHelper = statsHelper; mBatteryStatsHelper = statsHelper;
final long lastFullChargeTime = mBatteryUtils.calculateLastFullChargeTime(
mBatteryStatsHelper, System.currentTimeMillis());
final CharSequence timeSequence = StringUtil.formatRelativeTime(mContext,
lastFullChargeTime,
false);
final int resId = showAllApps ? R.string.power_usage_list_summary_device final int resId = showAllApps ? R.string.power_usage_list_summary_device
: R.string.power_usage_list_summary; : R.string.power_usage_list_summary;
mAppListGroup.setTitle(TextUtils.expandTemplate(mContext.getText(resId), timeSequence)); mAppListGroup.setTitle(TextUtils.expandTemplate(mContext.getText(resId), timeSequence));
@@ -361,7 +366,7 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
final long usageTimeMs = sipper.usageTimeMs; final long usageTimeMs = sipper.usageTimeMs;
if (usageTimeMs >= DateUtils.MINUTE_IN_MILLIS) { if (usageTimeMs >= DateUtils.MINUTE_IN_MILLIS) {
final CharSequence timeSequence = final CharSequence timeSequence =
StringUtil.formatElapsedTime(mContext, usageTimeMs, false); StringUtil.formatElapsedTime(mContext, usageTimeMs, false);
preference.setSummary( preference.setSummary(
(sipper.drainType != DrainType.APP || mBatteryUtils.shouldHideSipper(sipper)) (sipper.drainType != DrainType.APP || mBatteryUtils.shouldHideSipper(sipper))
? timeSequence ? timeSequence

View File

@@ -0,0 +1,176 @@
/*
* 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 android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import android.support.annotation.VisibleForTesting;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.utils.StringUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class PowerUsageAdvanced extends PowerUsageBase {
private static final String TAG = "AdvancedBatteryUsage";
private static final String KEY_BATTERY_GRAPH = "battery_graph";
private static final String KEY_APP_LIST = "app_list";
private static final String KEY_SHOW_ALL_APPS = "show_all_apps";
@VisibleForTesting
static final int MENU_TOGGLE_APPS = Menu.FIRST + 1;
@VisibleForTesting
BatteryHistoryPreference mHistPref;
private BatteryUtils mBatteryUtils;
private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
private BatteryAppListPreferenceController mBatteryAppListPreferenceController;
@VisibleForTesting
boolean mShowAllApps = false;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
final Context context = getContext();
mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_GRAPH);
mPowerUsageFeatureProvider = FeatureFactory.getFactory(context)
.getPowerUsageFeatureProvider(context);
mBatteryUtils = BatteryUtils.getInstance(context);
// init the summary so other preferences won't have unnecessary move
updateHistPrefSummary(context);
restoreSavedInstance(icicle);
}
@Override
public void onDestroy() {
super.onDestroy();
if (getActivity().isChangingConfigurations()) {
BatteryEntry.clearUidCache();
}
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.FUELGAUGE_BATTERY_HISTORY_DETAIL;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.power_usage_advanced;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add(Menu.NONE, MENU_TOGGLE_APPS, Menu.NONE,
mShowAllApps ? R.string.hide_extra_apps : R.string.show_all_apps);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_TOGGLE_APPS:
mShowAllApps = !mShowAllApps;
item.setTitle(mShowAllApps ? R.string.hide_extra_apps : R.string.show_all_apps);
mMetricsFeatureProvider.action(getContext(),
MetricsProto.MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE,
mShowAllApps);
restartBatteryStatsLoader();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@VisibleForTesting
void restoreSavedInstance(Bundle savedInstance) {
if (savedInstance != null) {
mShowAllApps = savedInstance.getBoolean(KEY_SHOW_ALL_APPS, false);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(KEY_SHOW_ALL_APPS, mShowAllApps);
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
mBatteryAppListPreferenceController = new BatteryAppListPreferenceController(context,
KEY_APP_LIST, getLifecycle(), (SettingsActivity) getActivity(), this);
controllers.add(mBatteryAppListPreferenceController);
return controllers;
}
@Override
protected void refreshUi() {
final Context context = getContext();
if (context == null) {
return;
}
updatePreference(mHistPref);
updateHistPrefSummary(context);
mBatteryAppListPreferenceController.refreshAppListGroup(mStatsHelper, mShowAllApps);
}
private void updateHistPrefSummary(Context context) {
Intent batteryIntent =
context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
final boolean plugged = batteryIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) != 0;
if (mPowerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(context) && !plugged) {
mHistPref.setBottomSummary(
mPowerUsageFeatureProvider.getAdvancedUsageScreenInfoString());
} else {
mHistPref.hideBottomSummary();
}
}
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.power_usage_advanced;
return Arrays.asList(sir);
}
};
}

View File

@@ -101,7 +101,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
SparseArray<List<Anomaly>> mAnomalySparseArray; SparseArray<List<Anomaly>> mAnomalySparseArray;
@VisibleForTesting @VisibleForTesting
BatteryHeaderPreferenceController mBatteryHeaderPreferenceController; BatteryHeaderPreferenceController mBatteryHeaderPreferenceController;
private BatteryAppListPreferenceController mBatteryAppListPreferenceController;
private BatteryTipPreferenceController mBatteryTipPreferenceController; private BatteryTipPreferenceController mBatteryTipPreferenceController;
private int mStatsType = BatteryStats.STATS_SINCE_CHARGED; private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
@@ -231,9 +230,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
mBatteryHeaderPreferenceController = new BatteryHeaderPreferenceController( mBatteryHeaderPreferenceController = new BatteryHeaderPreferenceController(
context, activity, this /* host */, lifecycle); context, activity, this /* host */, lifecycle);
controllers.add(mBatteryHeaderPreferenceController); controllers.add(mBatteryHeaderPreferenceController);
mBatteryAppListPreferenceController = new BatteryAppListPreferenceController(context,
KEY_APP_LIST, lifecycle, activity, this);
controllers.add(mBatteryAppListPreferenceController);
mBatteryTipPreferenceController = new BatteryTipPreferenceController(context, mBatteryTipPreferenceController = new BatteryTipPreferenceController(context,
KEY_BATTERY_TIP, (SettingsActivity) getActivity(), this /* fragment */, this /* KEY_BATTERY_TIP, (SettingsActivity) getActivity(), this /* fragment */, this /*
BatteryTipListener */); BatteryTipListener */);
@@ -294,11 +290,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
updateLastFullChargePreference(lastFullChargeTime); updateLastFullChargePreference(lastFullChargeTime);
mScreenUsagePref.setSubtitle(StringUtil.formatElapsedTime(getContext(), mScreenUsagePref.setSubtitle(StringUtil.formatElapsedTime(getContext(),
mBatteryUtils.calculateScreenUsageTime(mStatsHelper), false)); mBatteryUtils.calculateScreenUsageTime(mStatsHelper), false));
final CharSequence timeSequence = StringUtil.formatRelativeTime(context, lastFullChargeTime,
false);
mBatteryAppListPreferenceController.refreshAppListGroup(mStatsHelper,
false /* showAllApps */, timeSequence);
} }
@VisibleForTesting @VisibleForTesting

View File

@@ -202,20 +202,6 @@ public class BatteryAppListPreferenceControllerTest {
assertThat(mPreferenceController.shouldHideSipper(mNormalBatterySipper)).isFalse(); assertThat(mPreferenceController.shouldHideSipper(mNormalBatterySipper)).isFalse();
} }
@Test
public void testIsAvailable_featureOn_returnTrue() {
FeatureFlagUtils.setEnabled(mContext, FeatureFlags.BATTERY_DISPLAY_APP_LIST, true);
assertThat(mPreferenceController.isAvailable()).isTrue();
}
@Test
public void testIsAvailable_featureOff_returnFalse() {
FeatureFlagUtils.setEnabled(mContext, FeatureFlags.BATTERY_DISPLAY_APP_LIST, false);
assertThat(mPreferenceController.isAvailable()).isFalse();
}
@Test @Test
public void testNeverUseFakeData() { public void testNeverUseFakeData() {
assertThat(BatteryAppListPreferenceController.USE_FAKE_DATA).isFalse(); assertThat(BatteryAppListPreferenceController.USE_FAKE_DATA).isFalse();

View File

@@ -0,0 +1,111 @@
/*
* 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 static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doNothing;
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.content.Context;
import android.os.Bundle;
import android.support.v7.preference.PreferenceScreen;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.TestConfig;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class PowerUsageAdvancedTest {
@Mock
private PreferenceScreen mPreferenceScreen;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Menu mMenu;
@Mock
private MenuInflater mMenuInflater;
@Mock
private MenuItem mToggleAppsMenu;
private Context mContext;
private PowerUsageAdvanced mFragment;
private FakeFeatureFactory mFeatureFactory;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mFeatureFactory = FakeFeatureFactory.setupForTest();
when(mToggleAppsMenu.getItemId()).thenReturn(PowerUsageAdvanced.MENU_TOGGLE_APPS);
mFragment = spy(new PowerUsageAdvanced());
mFragment.onAttach(mContext);
}
@Test
public void testSaveInstanceState_showAllAppsRestored() {
Bundle bundle = new Bundle();
mFragment.mShowAllApps = true;
doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
mFragment.onSaveInstanceState(bundle);
mFragment.restoreSavedInstance(bundle);
assertThat(mFragment.mShowAllApps).isTrue();
}
@Test
public void testOptionsMenu_menuAppToggle_metricEventInvoked() {
mFragment.mShowAllApps = false;
doNothing().when(mFragment).restartBatteryStatsLoader();
mFragment.onOptionsItemSelected(mToggleAppsMenu);
verify(mFeatureFactory.metricsFeatureProvider).action(nullable(Context.class),
eq(MetricsProto.MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE), eq(true));
}
@Test
public void testOptionsMenu_toggleAppsEnabled() {
when(mFeatureFactory.powerUsageFeatureProvider.isPowerAccountingToggleEnabled())
.thenReturn(true);
mFragment.mShowAllApps = false;
mFragment.onCreateOptionsMenu(mMenu, mMenuInflater);
verify(mMenu).add(Menu.NONE, PowerUsageAdvanced.MENU_TOGGLE_APPS, Menu.NONE,
R.string.show_all_apps);
}
}