From cdd73e7fec48f2d228ccf42c42eebcdb692926a1 Mon Sep 17 00:00:00 2001 From: ykhung Date: Fri, 9 Apr 2021 11:43:22 +0800 Subject: [PATCH] Add kill-switch to distinguish chart or non-chart design Bug: 184807417 Bug: 180607918 Test: make SettingsRoboTests Test: make SettingsGoogleRoboTests Change-Id: Iacbb012209d552b58b774f90f5b0aeb60ce6d33d --- .../BatteryChartPreferenceController.java | 86 +++++++++++++++++ .../settings/fuelgauge/BatteryChartView.java | 2 + .../fuelgauge/BatteryHistoryLoader.java | 48 ++++++++++ .../fuelgauge/PowerUsageAdvanced.java | 95 +++++++++++++++++-- .../settings/fuelgauge/PowerUsageBase.java | 8 +- .../fuelgauge/BatteryHistoryLoaderTest.java | 61 ++++++++++++ 6 files changed, 284 insertions(+), 16 deletions(-) create mode 100644 src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java create mode 100644 src/com/android/settings/fuelgauge/BatteryHistoryLoader.java create mode 100644 tests/robotests/src/com/android/settings/fuelgauge/BatteryHistoryLoaderTest.java diff --git a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java new file mode 100644 index 00000000000..c8a7bc35869 --- /dev/null +++ b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java @@ -0,0 +1,86 @@ +/* + * 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 android.content.Context; +import android.util.Log; + +import androidx.preference.Preference; +import androidx.preference.PreferenceGroup; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.SettingsActivity; +import com.android.settings.core.InstrumentedPreferenceFragment; +import com.android.settings.core.PreferenceControllerMixin; +import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnDestroy; +import com.android.settingslib.core.lifecycle.events.OnPause; + +import java.util.List; +import java.util.Map; + +/** Cotrols the update for chart graph and the list items. */ +public class BatteryChartPreferenceController extends AbstractPreferenceController + implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy { + private static final String TAG = "BatteryChartPreferenceController"; + + private final String mPreferenceKey; + + public BatteryChartPreferenceController( + Context context, String chartPreferenceKey, String listPreferenceKey, + Lifecycle lifecycle, SettingsActivity activity, + InstrumentedPreferenceFragment fragment) { + super(context); + mPreferenceKey = listPreferenceKey; + } + + + @Override + public void onPause() { + } + + @Override + public void onDestroy() { + } + + @Override + public void displayPreference(PreferenceScreen screen) { + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public String getPreferenceKey() { + return mPreferenceKey; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + void refreshUi(Map> batteryHistoryMap) { + Log.d(TAG, "refreshUi:" + batteryHistoryMap.size()); + } +} diff --git a/src/com/android/settings/fuelgauge/BatteryChartView.java b/src/com/android/settings/fuelgauge/BatteryChartView.java index 47333aa0160..d9a93b10ef3 100644 --- a/src/com/android/settings/fuelgauge/BatteryChartView.java +++ b/src/com/android/settings/fuelgauge/BatteryChartView.java @@ -74,7 +74,9 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick public BatteryChartView(Context context, AttributeSet attrs) { super(context, attrs); initializeColors(context); + // Registers the click event listener. setOnClickListener(this); + setClickable(false); setSelectedIndex(SELECTED_INDEX_ALL); setTrapezoidCount(DEFAULT_TRAPEZOID_COUNT); } diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryLoader.java b/src/com/android/settings/fuelgauge/BatteryHistoryLoader.java new file mode 100644 index 00000000000..97bdbd630a2 --- /dev/null +++ b/src/com/android/settings/fuelgauge/BatteryHistoryLoader.java @@ -0,0 +1,48 @@ +/* + * 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 android.content.Context; + +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.utils.AsyncLoaderCompat; + +import java.util.List; +import java.util.Map; + +/** Loader that can be used to load battery history information. */ +public class BatteryHistoryLoader + extends AsyncLoaderCompat>> { + private static final String TAG = "BatteryHistoryLoader"; + + private final Context mContext; + + public BatteryHistoryLoader(Context context) { + super(context); + mContext = context; + } + + @Override + protected void onDiscardResult(Map> result) { + } + + @Override + public Map> loadInBackground() { + final PowerUsageFeatureProvider powerUsageFeatureProvider = + FeatureFactory.getFactory(mContext).getPowerUsageFeatureProvider(mContext); + return powerUsageFeatureProvider.getBatteryHistory(mContext); + } +} diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java index 0727e48ebc9..d5f443c802c 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java +++ b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java @@ -20,8 +20,12 @@ import android.content.Context; import android.os.BatteryManager; import android.os.Bundle; import android.provider.SearchIndexableResource; +import android.util.Log; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; +import androidx.loader.app.LoaderManager; +import androidx.loader.content.Loader; import com.android.settings.R; import com.android.settings.SettingsActivity; @@ -33,26 +37,38 @@ import com.android.settingslib.search.SearchIndexable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) public class PowerUsageAdvanced extends PowerUsageBase { private static final String TAG = "AdvancedBatteryUsage"; + private static final String KEY_REFRESH_TYPE = "refresh_type"; private static final String KEY_BATTERY_GRAPH = "battery_graph"; private static final String KEY_APP_LIST = "app_list"; + private static final int LOADER_BATTERY_USAGE_STATS = 2; @VisibleForTesting BatteryHistoryPreference mHistPref; + @VisibleForTesting + Map> mBatteryHistoryMap; + @VisibleForTesting + final BatteryHistoryLoaderCallbacks mBatteryHistoryLoaderCallbacks = + new BatteryHistoryLoaderCallbacks(); + + private boolean mIsChartGraphEnabled = false; private PowerUsageFeatureProvider mPowerUsageFeatureProvider; + private BatteryChartPreferenceController mBatteryChartPreferenceController; private BatteryAppListPreferenceController mBatteryAppListPreferenceController; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); - final Context context = getContext(); - + refreshFeatureFlag(getContext()); mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_GRAPH); - mPowerUsageFeatureProvider = FeatureFactory.getFactory(context) - .getPowerUsageFeatureProvider(context); + // Removes chart graph preference if the chart design is disabled. + if (!mIsChartGraphEnabled) { + removePreference(KEY_BATTERY_GRAPH); + } } @Override @@ -80,12 +96,21 @@ public class PowerUsageAdvanced extends PowerUsageBase { @Override protected List createPreferenceControllers(Context context) { + refreshFeatureFlag(context); final List controllers = new ArrayList<>(); - - mBatteryAppListPreferenceController = new BatteryAppListPreferenceController(context, - KEY_APP_LIST, getSettingsLifecycle(), (SettingsActivity) getActivity(), this); - controllers.add(mBatteryAppListPreferenceController); - + // Creates based on the chart design is enabled or not. + if (mIsChartGraphEnabled) { + mBatteryChartPreferenceController = + new BatteryChartPreferenceController(context, + KEY_BATTERY_GRAPH, KEY_APP_LIST, + getSettingsLifecycle(), (SettingsActivity) getActivity(), this); + controllers.add(mBatteryChartPreferenceController); + } else { + mBatteryAppListPreferenceController = + new BatteryAppListPreferenceController(context, KEY_APP_LIST, + getSettingsLifecycle(), (SettingsActivity) getActivity(), this); + controllers.add(mBatteryAppListPreferenceController); + } return controllers; } @@ -101,7 +126,34 @@ public class PowerUsageAdvanced extends PowerUsageBase { return; } updatePreference(mHistPref); - mBatteryAppListPreferenceController.refreshAppListGroup(mBatteryUsageStats, true); + if (mBatteryAppListPreferenceController != null && mBatteryUsageStats != null) { + mBatteryAppListPreferenceController.refreshAppListGroup( + mBatteryUsageStats, /* showAllApps */true); + } + if (mBatteryChartPreferenceController != null && mBatteryHistoryMap != null) { + mBatteryChartPreferenceController.refreshUi(mBatteryHistoryMap); + } + } + + @Override + protected void restartBatteryStatsLoader(int refreshType) { + final Bundle bundle = new Bundle(); + bundle.putInt(KEY_REFRESH_TYPE, refreshType); + // Uses customized battery history loader if chart design is enabled. + if (mIsChartGraphEnabled) { + getLoaderManager().restartLoader(LOADER_BATTERY_USAGE_STATS, bundle, + mBatteryHistoryLoaderCallbacks); + } else { + super.restartBatteryStatsLoader(refreshType); + } + } + + private void refreshFeatureFlag(Context context) { + if (mPowerUsageFeatureProvider == null) { + mPowerUsageFeatureProvider = FeatureFactory.getFactory(context) + .getPowerUsageFeatureProvider(context); + mIsChartGraphEnabled = mPowerUsageFeatureProvider.isChartGraphEnabled(context); + } } public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = @@ -125,4 +177,27 @@ public class PowerUsageAdvanced extends PowerUsageBase { } }; + private class BatteryHistoryLoaderCallbacks + implements LoaderManager.LoaderCallbacks>> { + private int mRefreshType; + + @Override + @NonNull + public Loader>> onCreateLoader(int id, Bundle bundle) { + mRefreshType = bundle.getInt(KEY_REFRESH_TYPE); + return new BatteryHistoryLoader(getContext()); + } + + @Override + public void onLoadFinished(Loader>> loader, + Map> batteryHistoryMap) { + mBatteryHistoryMap = batteryHistoryMap; + PowerUsageAdvanced.this.onLoadFinished(mRefreshType); + } + + @Override + public void onLoaderReset(Loader>> loader) { + } + } + } diff --git a/src/com/android/settings/fuelgauge/PowerUsageBase.java b/src/com/android/settings/fuelgauge/PowerUsageBase.java index 28d77159938..16567fee07c 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageBase.java +++ b/src/com/android/settings/fuelgauge/PowerUsageBase.java @@ -36,9 +36,6 @@ import com.android.settings.dashboard.DashboardFragment; */ public abstract class PowerUsageBase extends DashboardFragment { - // +1 to allow ordering for PowerUsageSummary. - @VisibleForTesting - static final int MENU_STATS_REFRESH = Menu.FIRST + 1; private static final String TAG = "PowerUsageBase"; private static final String KEY_REFRESH_TYPE = "refresh_type"; private static final String KEY_INCLUDE_HISTORY = "include_history"; @@ -49,8 +46,8 @@ public abstract class PowerUsageBase extends DashboardFragment { BatteryUsageStats mBatteryUsageStats; protected UserManager mUm; - private BatteryBroadcastReceiver mBatteryBroadcastReceiver; protected boolean mIsBatteryPresent = true; + private BatteryBroadcastReceiver mBatteryBroadcastReceiver; @VisibleForTesting final BatteryUsageStatsLoaderCallbacks mBatteryUsageStatsLoaderCallbacks = @@ -65,7 +62,6 @@ public abstract class PowerUsageBase extends DashboardFragment { @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); - setHasOptionsMenu(true); mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(getContext()); mBatteryBroadcastReceiver.setBatteryChangedListener(type -> { @@ -96,7 +92,7 @@ public abstract class PowerUsageBase extends DashboardFragment { mBatteryUsageStatsLoaderCallbacks); } - private void onLoadFinished(@BatteryUpdateType int refreshType) { + protected void onLoadFinished(@BatteryUpdateType int refreshType) { refreshUi(refreshType); } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistoryLoaderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistoryLoaderTest.java new file mode 100644 index 00000000000..c3ab5e50ea9 --- /dev/null +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistoryLoaderTest.java @@ -0,0 +1,61 @@ +/* + * 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.Mockito.doReturn; + +import android.content.Context; + +import com.android.settings.testutils.FakeFeatureFactory; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@RunWith(RobolectricTestRunner.class) +public final class BatteryHistoryLoaderTest { + + private Context mContext; + private FakeFeatureFactory mFeatureFactory; + private BatteryHistoryLoader mBatteryHistoryLoader; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = RuntimeEnvironment.application; + mFeatureFactory = FakeFeatureFactory.setupForTest(); + mBatteryHistoryLoader = new BatteryHistoryLoader(mContext); + } + + @Test + public void testLoadIBackground_returnsMapFromPowerFeatureProvider() { + final Map> batteryHistoryMap = new HashMap<>(); + doReturn(batteryHistoryMap).when(mFeatureFactory.powerUsageFeatureProvider) + .getBatteryHistory(mContext); + + assertThat(mBatteryHistoryLoader.loadInBackground()) + .isSameInstanceAs(batteryHistoryMap); + } +}