Migrate Spinner on Battery Usage to settingsLib Spinner widget.
Bug: 359429437
Test: visual
Test: atest BatteryUsageBreakdownControllerTest
Flag: EXEMPT bug fix
Change-Id: I71bd1f31db302d407603c71d1a1163ed22fafed8
diff --git a/res/layout/preference_spinner.xml b/res/layout/preference_spinner.xml
deleted file mode 100644
index 4129303..0000000
--- a/res/layout/preference_spinner.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
- ~ Copyright (C) 2023 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.
- -->
-
-<Spinner
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/spinner"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="24dp"
- android:layout_marginTop="8dp"
- android:theme="@style/Widget.PopupWindow.Settings" />
diff --git a/res/xml/power_usage_advanced.xml b/res/xml/power_usage_advanced.xml
index 816e197..f2c3d87 100644
--- a/res/xml/power_usage_advanced.xml
+++ b/res/xml/power_usage_advanced.xml
@@ -57,7 +57,7 @@
"com.android.settings.fuelgauge.batteryusage.BatteryUsageBreakdownController"
settings:isPreferenceVisible="false">
- <com.android.settings.fuelgauge.batteryusage.SpinnerPreference
+ <com.android.settingslib.widget.SettingsSpinnerPreference
android:key="battery_usage_spinner"
settings:isPreferenceVisible="false" />
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java
index f451f0a..09940b3 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
@@ -46,9 +47,13 @@
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnCreate;
import com.android.settingslib.core.lifecycle.events.OnDestroy;
import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
import com.android.settingslib.widget.FooterPreference;
+import com.android.settingslib.widget.SettingsSpinnerAdapter;
+import com.android.settingslib.widget.SettingsSpinnerPreference;
import java.util.ArrayList;
import java.util.List;
@@ -58,7 +63,7 @@
/** Controller for battery usage breakdown preference group. */
public class BatteryUsageBreakdownController extends BasePreferenceController
- implements LifecycleObserver, OnResume, OnDestroy {
+ implements LifecycleObserver, OnResume, OnDestroy, OnCreate, OnSaveInstanceState {
private static final String TAG = "BatteryUsageBreakdownController";
private static final String ROOT_PREFERENCE_KEY = "battery_usage_breakdown";
private static final String FOOTER_PREFERENCE_KEY = "battery_usage_footer";
@@ -67,6 +72,7 @@
private static final String PACKAGE_NAME_NONE = "none";
private static final String SLOT_TIMESTAMP = "slot_timestamp";
private static final String ANOMALY_KEY = "anomaly_key";
+ private static final String KEY_SPINNER_POSITION = "spinner_position";
private static final List<BatteryDiffEntry> EMPTY_ENTRY_LIST = new ArrayList<>();
private static int sUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
@@ -78,12 +84,12 @@
@VisibleForTesting final Map<String, Preference> mPreferenceCache = new ArrayMap<>();
- private int mSpinnerPosition;
private String mSlotInformation;
+ private SettingsSpinnerPreference mSpinnerPreference;
+ private SettingsSpinnerAdapter<CharSequence> mSpinnerAdapter;
@VisibleForTesting Context mPrefContext;
@VisibleForTesting PreferenceCategory mRootPreference;
- @VisibleForTesting SpinnerPreference mSpinnerPreference;
@VisibleForTesting PreferenceGroup mAppListPreferenceGroup;
@VisibleForTesting FooterPreference mFooterPreference;
@VisibleForTesting BatteryDiffData mBatteryDiffData;
@@ -92,6 +98,7 @@
@VisibleForTesting String mPercentLessThanThresholdContentDescription;
@VisibleForTesting boolean mIsHighlightSlot;
@VisibleForTesting int mAnomalyKeyNumber;
+ @VisibleForTesting int mSpinnerPosition;
@VisibleForTesting String mAnomalyEntryKey;
@VisibleForTesting String mAnomalyHintString;
@VisibleForTesting String mAnomalyHintPrefKey;
@@ -111,6 +118,15 @@
}
@Override
+ public void onCreate(Bundle savedInstanceState) {
+ if (savedInstanceState == null) {
+ return;
+ }
+ mSpinnerPosition = savedInstanceState.getInt(KEY_SPINNER_POSITION, mSpinnerPosition);
+ Log.d(TAG, "onCreate() spinnerPosition=" + mSpinnerPosition);
+ }
+
+ @Override
public void onResume() {
final int currentUiMode =
mContext.getResources().getConfiguration().uiMode
@@ -140,6 +156,15 @@
return false;
}
+ @Override
+ public void onSaveInstanceState(Bundle savedInstanceState) {
+ if (savedInstanceState == null) {
+ return;
+ }
+ savedInstanceState.putInt(KEY_SPINNER_POSITION, mSpinnerPosition);
+ Log.d(TAG, "onSaveInstanceState() spinnerPosition=" + mSpinnerPosition);
+ }
+
private boolean isAnomalyBatteryDiffEntry(BatteryDiffEntry entry) {
return mIsHighlightSlot
&& mAnomalyEntryKey != null
@@ -218,11 +243,14 @@
formatPercentage);
mAppListPreferenceGroup.setOrderingAsAdded(false);
- mSpinnerPreference.initializeSpinner(
+ mSpinnerAdapter = new SettingsSpinnerAdapter<>(mPrefContext);
+ mSpinnerAdapter.addAll(
new String[] {
mPrefContext.getString(R.string.battery_usage_spinner_view_by_apps),
mPrefContext.getString(R.string.battery_usage_spinner_view_by_systems)
- },
+ });
+ mSpinnerPreference.setAdapter(mSpinnerAdapter);
+ mSpinnerPreference.setOnItemSelectedListener(
new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(
@@ -244,6 +272,7 @@
@Override
public void onNothingSelected(AdapterView<?> parent) {}
});
+ mSpinnerPreference.setSelection(mSpinnerPosition);
}
/**
diff --git a/src/com/android/settings/fuelgauge/batteryusage/SpinnerPreference.java b/src/com/android/settings/fuelgauge/batteryusage/SpinnerPreference.java
deleted file mode 100644
index 886d00d..0000000
--- a/src/com/android/settings/fuelgauge/batteryusage/SpinnerPreference.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2023 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.batteryusage;
-
-import android.content.Context;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.widget.AdapterView;
-import android.widget.Spinner;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.settings.R;
-import com.android.settingslib.widget.SettingsSpinnerAdapter;
-
-/** A preference which contains a spinner. */
-public class SpinnerPreference extends Preference {
- private static final String TAG = "SpinnerPreference";
-
- private AdapterView.OnItemSelectedListener mOnItemSelectedListener;
-
- @VisibleForTesting Spinner mSpinner;
- @VisibleForTesting String[] mItems;
- @VisibleForTesting int mSavedSpinnerPosition;
-
- public SpinnerPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- setLayoutResource(R.layout.preference_spinner);
- }
-
- void initializeSpinner(
- String[] items, AdapterView.OnItemSelectedListener onItemSelectedListener) {
- mItems = items;
- mOnItemSelectedListener = onItemSelectedListener;
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder view) {
- if (mSpinner != null) {
- return;
- }
-
- mSpinner = (Spinner) view.findViewById(R.id.spinner);
- mSpinner.setAdapter(new SpinnerAdapter(getContext(), mItems));
- mSpinner.setSelection(mSavedSpinnerPosition);
- mSpinner.setLongClickable(false);
- if (mOnItemSelectedListener != null) {
- mSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
- }
- }
-
- @Override
- protected Parcelable onSaveInstanceState() {
- if (mSpinner == null) {
- return super.onSaveInstanceState();
- }
- Log.d(TAG, "onSaveInstanceState() spinnerPosition=" + mSpinner.getSelectedItemPosition());
- return new SavedState(super.onSaveInstanceState(), mSpinner.getSelectedItemPosition());
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- if (state == null || state == BaseSavedState.EMPTY_STATE) {
- super.onRestoreInstanceState(state);
- return;
- }
- if (!(state instanceof SavedState)) {
- // To avoid the IllegalArgumentException, return the BaseSavedState.EMPTY_STATE.
- super.onRestoreInstanceState(BaseSavedState.EMPTY_STATE);
- return;
- }
- SavedState savedState = (SavedState) state;
- super.onRestoreInstanceState(savedState.getSuperState());
- mSavedSpinnerPosition = savedState.getSpinnerPosition();
- if (mOnItemSelectedListener != null) {
- mOnItemSelectedListener.onItemSelected(
- /* parent= */ null,
- /* view= */ null,
- savedState.getSpinnerPosition(),
- /* id= */ 0);
- }
- Log.d(TAG, "onRestoreInstanceState() spinnerPosition=" + savedState.getSpinnerPosition());
- }
-
- @VisibleForTesting
- static class SavedState extends BaseSavedState {
- private int mSpinnerPosition;
-
- SavedState(Parcelable superState, int spinnerPosition) {
- super(superState);
- mSpinnerPosition = spinnerPosition;
- }
-
- int getSpinnerPosition() {
- return mSpinnerPosition;
- }
- }
-
- private static class SpinnerAdapter extends SettingsSpinnerAdapter<CharSequence> {
- private final String[] mItems;
-
- SpinnerAdapter(Context context, String[] items) {
- super(context);
- mItems = items;
- }
-
- @Override
- public int getCount() {
- return mItems.length;
- }
-
- @Override
- public CharSequence getItem(int position) {
- return mItems[position];
- }
- }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
index 4c64808..85fc6e2 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
@@ -29,6 +29,7 @@
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.os.LocaleList;
import android.text.format.DateUtils;
@@ -57,6 +58,7 @@
private static final String PREF_KEY = "pref_key";
private static final String PREF_KEY2 = "pref_key2";
private static final String PREF_SUMMARY = "fake preference summary";
+ private static final String KEY_SPINNER_POSITION = "spinner_position";
private static final long TIME_LESS_THAN_HALF_MINUTE = DateUtils.MINUTE_IN_MILLIS / 2 - 1;
@Mock private InstrumentedPreferenceFragment mFragment;
@@ -149,6 +151,15 @@
}
@Test
+ public void onSaveInstanceState_returnExpectedResult() {
+ mBatteryUsageBreakdownController.mSpinnerPosition = 1;
+ final Bundle savedInstanceState = new Bundle();
+ mBatteryUsageBreakdownController.onSaveInstanceState(savedInstanceState);
+
+ assertThat(savedInstanceState.getInt(KEY_SPINNER_POSITION)).isEqualTo(1);
+ }
+
+ @Test
public void addAllPreferences_addAllPreferences() {
final String appLabel = "fake app label";
doReturn(1).when(mAppListPreferenceGroup).getPreferenceCount();
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/SpinnerPreferenceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/SpinnerPreferenceTest.java
deleted file mode 100644
index 8050984..0000000
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/SpinnerPreferenceTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2022 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.batteryusage;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-
-import android.content.Context;
-import android.widget.Spinner;
-
-import androidx.preference.Preference;
-
-import com.android.settings.R;
-
-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;
-
-@RunWith(RobolectricTestRunner.class)
-public final class SpinnerPreferenceTest {
-
- private Context mContext;
- private SpinnerPreference mSpinnerPreference;
-
- @Mock private Spinner mMockSpinner;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mContext = spy(RuntimeEnvironment.application);
- mSpinnerPreference = new SpinnerPreference(mContext, /* attrs= */ null);
- }
-
- @Test
- public void constructor_returnExpectedResult() {
- assertThat(mSpinnerPreference.getLayoutResource()).isEqualTo(R.layout.preference_spinner);
- }
-
- @Test
- public void initializeSpinner_returnExpectedResult() {
- final String[] items = new String[] {"item1", "item2"};
- mSpinnerPreference.initializeSpinner(items, null);
- assertThat(mSpinnerPreference.mItems).isEqualTo(items);
- }
-
- @Test
- public void onSaveInstanceState_returnExpectedResult() {
- doReturn(1).when(mMockSpinner).getSelectedItemPosition();
- mSpinnerPreference.mSpinner = mMockSpinner;
- SpinnerPreference.SavedState savedState =
- (SpinnerPreference.SavedState) mSpinnerPreference.onSaveInstanceState();
- assertThat(savedState.getSpinnerPosition()).isEqualTo(1);
- }
-
- @Test
- public void onRestoreInstanceState_returnExpectedResult() {
- SpinnerPreference.SavedState savedState =
- new SpinnerPreference.SavedState(Preference.BaseSavedState.EMPTY_STATE, 2);
- mSpinnerPreference.onRestoreInstanceState(savedState);
- assertThat(mSpinnerPreference.mSavedSpinnerPosition).isEqualTo(2);
- }
-}