Merge "Tweak the layout of top app bar" into sc-dev
diff --git a/res/xml/power_usage_detail.xml b/res/xml/power_usage_detail.xml
index 95c1038..0258f8d 100644
--- a/res/xml/power_usage_detail.xml
+++ b/res/xml/power_usage_detail.xml
@@ -34,6 +34,30 @@
android:title="@string/battery_detail_manage_title"
settings:allowDividerAbove="true">
+ <com.android.settingslib.widget.RadioButtonPreference
+ android:key="unrestricted_pref"
+ android:summary="@string/manager_battery_usage_unrestricted_summary"
+ android:title="@string/manager_battery_usage_unrestricted_title"
+ settings:controller="com.android.settings.fuelgauge.UnrestrictedPreferenceController"/>
+
+ <com.android.settingslib.widget.RadioButtonPreference
+ android:key="optimized_pref"
+ android:summary="@string/manager_battery_usage_optimized_summary"
+ android:title="@string/manager_battery_usage_optimized_title"
+ settings:controller="com.android.settings.fuelgauge.OptimizedPreferenceController"/>
+
+ <com.android.settingslib.widget.RadioButtonPreference
+ android:key="restricted_pref"
+ android:summary="@string/manager_battery_usage_restricted_summary"
+ android:title="@string/restricted_true_label"
+ settings:controller="com.android.settings.fuelgauge.RestrictedPreferenceController"/>
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:title="@string/battery_detail_manage_title"
+ settings:allowDividerAbove="true">
+
<com.android.settingslib.RestrictedPreference
android:key="background_activity"
android:title="@string/background_activity_title"
@@ -63,4 +87,11 @@
</PreferenceCategory>
+ <com.android.settingslib.widget.FooterPreference
+ android:order="100"
+ android:key="app_usage_footer_preference"
+ android:title="@string/manager_battery_usage_footer"
+ android:selectable="true"
+ settings:searchable="false"/>
+
</PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index f4bdfb3..f28ae00 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -25,6 +25,7 @@
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.UserHandle;
+import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
@@ -48,6 +49,7 @@
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.utils.StringUtil;
import com.android.settingslib.widget.LayoutPreference;
+import com.android.settingslib.widget.RadioButtonPreference;
import java.util.ArrayList;
import java.util.List;
@@ -60,7 +62,7 @@
*/
public class AdvancedPowerUsageDetail extends DashboardFragment implements
ButtonActionDialogFragment.AppButtonsDialogListener,
- BatteryTipPreferenceController.BatteryTipListener {
+ BatteryTipPreferenceController.BatteryTipListener, RadioButtonPreference.OnClickListener {
public static final String TAG = "AdvancedPowerDetail";
public static final String EXTRA_UID = "extra_uid";
@@ -75,6 +77,10 @@
private static final String KEY_PREF_FOREGROUND = "app_usage_foreground";
private static final String KEY_PREF_BACKGROUND = "app_usage_background";
private static final String KEY_PREF_HEADER = "header_view";
+ private static final String KEY_PREF_UNRESTRICTED = "unrestricted_pref";
+ private static final String KEY_PREF_OPTIMIZED = "optimized_pref";
+ private static final String KEY_PREF_RESTRICTED = "restricted_pref";
+ private static final String KEY_FOOTER_PREFERENCE = "app_usage_footer_preference";
private static final int REQUEST_UNINSTALL = 0;
private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1;
@@ -87,13 +93,26 @@
ApplicationsState.AppEntry mAppEntry;
@VisibleForTesting
BatteryUtils mBatteryUtils;
+ @VisibleForTesting
+ BatteryOptimizeUtils mBatteryOptimizeUtils;
@VisibleForTesting
Preference mForegroundPreference;
@VisibleForTesting
Preference mBackgroundPreference;
+ @VisibleForTesting
+ Preference mFooterPreference;
+ @VisibleForTesting
+ RadioButtonPreference mRestrictedPreference;
+ @VisibleForTesting
+ RadioButtonPreference mOptimizePreference;
+ @VisibleForTesting
+ RadioButtonPreference mUnrestrictedPreference;
private AppButtonsPreferenceController mAppButtonsPreferenceController;
private BackgroundActivityPreferenceController mBackgroundActivityPreferenceController;
+ private UnrestrictedPreferenceController mUnrestrictedPreferenceController;
+ private OptimizedPreferenceController mOptimizedPreferenceController;
+ private RestrictedPreferenceController mRestrictedPreferenceController;
private String mPackageName;
@@ -174,8 +193,19 @@
mPackageName = getArguments().getString(EXTRA_PACKAGE_NAME);
mForegroundPreference = findPreference(KEY_PREF_FOREGROUND);
mBackgroundPreference = findPreference(KEY_PREF_BACKGROUND);
+ mFooterPreference = findPreference(KEY_FOOTER_PREFERENCE);
mHeaderPreference = (LayoutPreference) findPreference(KEY_PREF_HEADER);
+ mUnrestrictedPreference = findPreference(KEY_PREF_UNRESTRICTED);
+ mOptimizePreference = findPreference(KEY_PREF_OPTIMIZED);
+ mRestrictedPreference = findPreference(KEY_PREF_RESTRICTED);
+ mUnrestrictedPreference.setOnClickListener(this);
+ mOptimizePreference.setOnClickListener(this);
+ mRestrictedPreference.setOnClickListener(this);
+
+ mBatteryOptimizeUtils = new BatteryOptimizeUtils(
+ getContext(), getArguments().getInt(EXTRA_UID), mPackageName);
+
if (mPackageName != null) {
mAppEntry = mState.getEntry(mPackageName, UserHandle.myUserId());
}
@@ -241,6 +271,26 @@
backgroundTimeMs,
/* withSeconds */ false,
/* collapseTimeUnit */ false)));
+
+ final String stateString;
+ final String footerString;
+ //TODO(b/178197718) Update strings
+ if (!mBatteryOptimizeUtils.isValidPackageName()) {
+ //Present optimized only string when the package name is invalid.
+ stateString = context.getString(R.string.manager_battery_usage_optimized_title);
+ footerString = context.getString(
+ R.string.manager_battery_usage_footer_limited, stateString);
+ } else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
+ //Present unrestricted only string when the package is system or default active app.
+ stateString = context.getString(R.string.manager_battery_usage_unrestricted_title);
+ footerString = context.getString(
+ R.string.manager_battery_usage_footer_limited, stateString);
+ } else {
+ //Present default string to normal app.
+ footerString = context.getString(R.string.manager_battery_usage_footer);
+
+ }
+ mFooterPreference.setTitle(Html.fromHtml(footerString, Html.FROM_HTML_MODE_COMPACT));
}
@Override
@@ -274,6 +324,15 @@
(SettingsActivity) getActivity(), this, getSettingsLifecycle(), packageName, mState,
REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN);
controllers.add(mAppButtonsPreferenceController);
+ mUnrestrictedPreferenceController =
+ new UnrestrictedPreferenceController(context, uid, packageName);
+ mOptimizedPreferenceController =
+ new OptimizedPreferenceController(context, uid, packageName);
+ mRestrictedPreferenceController =
+ new RestrictedPreferenceController(context, uid, packageName);
+ controllers.add(mUnrestrictedPreferenceController);
+ controllers.add(mOptimizedPreferenceController);
+ controllers.add(mRestrictedPreferenceController);
return controllers;
}
@@ -298,4 +357,15 @@
mBackgroundActivityPreferenceController.updateSummary(
findPreference(mBackgroundActivityPreferenceController.getPreferenceKey()));
}
+
+ @Override
+ public void onRadioButtonClicked(RadioButtonPreference selected) {
+ updatePreferenceState(mUnrestrictedPreference, selected.getKey());
+ updatePreferenceState(mOptimizePreference, selected.getKey());
+ updatePreferenceState(mRestrictedPreference, selected.getKey());
+ }
+
+ private void updatePreferenceState(RadioButtonPreference preference, String selectedKey) {
+ preference.setChecked(selectedKey.equals(preference.getKey()));
+ }
}
diff --git a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
new file mode 100644
index 0000000..1184a77
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
@@ -0,0 +1,121 @@
+/*
+ * 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.app.AppOpsManager;
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
+
+/** A utility class for application usage operation. */
+public class BatteryOptimizeUtils {
+ private static final String TAG = "BatteryOptimizeUtils";
+
+ @VisibleForTesting AppOpsManager mAppOpsManager;
+ @VisibleForTesting BatteryUtils mBatteryUtils;
+ @VisibleForTesting PowerAllowlistBackend mPowerAllowListBackend;
+ private final String mPackageName;
+ private final int mUid;
+
+ private int mMode;
+ private boolean mAllowListed;
+
+ /**
+ * Usage type of application.
+ */
+ public enum AppUsageState {
+ UNKNOWN,
+ RESTRICTED,
+ UNRESTRICTED,
+ OPTIMIZED,
+ }
+
+ public BatteryOptimizeUtils(Context context, int uid, String packageName) {
+ mUid = uid;
+ mPackageName = packageName;
+ mAppOpsManager = context.getSystemService(AppOpsManager.class);
+ mBatteryUtils = BatteryUtils.getInstance(context);
+ mPowerAllowListBackend = PowerAllowlistBackend.getInstance(context);
+ mMode = mAppOpsManager
+ .checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mPackageName);
+ mAllowListed = mPowerAllowListBackend.isAllowlisted(mPackageName);
+ }
+
+ public AppUsageState getAppUsageState() {
+ refreshState();
+ if (!mAllowListed && mMode == AppOpsManager.MODE_IGNORED) {
+ return AppUsageState.RESTRICTED;
+ } else if (mAllowListed && mMode == AppOpsManager.MODE_ALLOWED) {
+ return AppUsageState.UNRESTRICTED;
+ } else if (!mAllowListed && mMode == AppOpsManager.MODE_ALLOWED) {
+ return AppUsageState.OPTIMIZED;
+ } else {
+ Log.d(TAG, "get unknown app usage state.");
+ return AppUsageState.UNKNOWN;
+ }
+ }
+
+ public void setAppUsageState(AppUsageState state) {
+ switch (state) {
+ case RESTRICTED:
+ mBatteryUtils.setForceAppStandby(mUid, mPackageName, AppOpsManager.MODE_IGNORED);
+ mPowerAllowListBackend.removeApp(mPackageName);
+ break;
+ case UNRESTRICTED:
+ mBatteryUtils.setForceAppStandby(mUid, mPackageName, AppOpsManager.MODE_ALLOWED);
+ mPowerAllowListBackend.addApp(mPackageName);
+ break;
+ case OPTIMIZED:
+ mBatteryUtils.setForceAppStandby(mUid, mPackageName, AppOpsManager.MODE_ALLOWED);
+ mPowerAllowListBackend.removeApp(mPackageName);
+ break;
+ default:
+ Log.d(TAG, "set unknown app usage state.");
+ }
+ }
+
+ /**
+ * Return {@code true} if package name is valid (can get an uid).
+ */
+ public boolean isValidPackageName() {
+ return mBatteryUtils.getPackageUid(mPackageName) != BatteryUtils.UID_NULL;
+ }
+
+ /**
+ * Return {@code true} if this package is system or default active app.
+ */
+ public boolean isSystemOrDefaultApp() {
+ mPowerAllowListBackend.refreshList();
+
+ return mPowerAllowListBackend.isSysAllowlisted(mPackageName)
+ || mPowerAllowListBackend.isDefaultActiveApp(mPackageName);
+ }
+
+ private void refreshState() {
+ mPowerAllowListBackend.refreshList();
+ mAllowListed = mPowerAllowListBackend.isAllowlisted(mPackageName);
+ mMode = mAppOpsManager
+ .checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mPackageName);
+ Log.d(TAG, String.format("refresh %s state, allowlisted = %s, mode = %d",
+ mPackageName,
+ mAllowListed,
+ mMode));
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java b/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
new file mode 100644
index 0000000..b2da356
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
@@ -0,0 +1,85 @@
+/*
+ * 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.android.settings.fuelgauge.BatteryOptimizeUtils.AppUsageState.OPTIMIZED;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+public class OptimizedPreferenceController extends AbstractPreferenceController
+ implements PreferenceControllerMixin {
+
+ private static final String TAG = "OPTIMIZED_PREF";
+
+ @VisibleForTesting String KEY_OPTIMIZED_PREF = "optimized_pref";
+ @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
+
+ public OptimizedPreferenceController(Context context, int uid, String packageName) {
+ super(context);
+ mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ if (!mBatteryOptimizeUtils.isValidPackageName()) {
+ Log.d(TAG, "invalid package name, optimized states only");
+ preference.setEnabled(true);
+ ((RadioButtonPreference) preference).setChecked(true);
+ return;
+ }
+
+ if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
+ Log.d(TAG, "is system or default app, disable pref");
+ ((RadioButtonPreference) preference).setChecked(false);
+ preference.setEnabled(false);
+ } else if (mBatteryOptimizeUtils.getAppUsageState() == OPTIMIZED) {
+ Log.d(TAG, "is optimized states");
+ ((RadioButtonPreference) preference).setChecked(true);
+ } else {
+ ((RadioButtonPreference) preference).setChecked(false);
+ }
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_OPTIMIZED_PREF;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!KEY_OPTIMIZED_PREF.equals(preference.getKey())) {
+ return false;
+ }
+
+ mBatteryOptimizeUtils.setAppUsageState(OPTIMIZED);
+ Log.d(TAG, "Set optimized");
+ return true;
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java b/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java
new file mode 100644
index 0000000..b52af57
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java
@@ -0,0 +1,88 @@
+/*
+ * 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.android.settings.fuelgauge.BatteryOptimizeUtils.AppUsageState.RESTRICTED;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+public class RestrictedPreferenceController extends AbstractPreferenceController
+ implements PreferenceControllerMixin {
+
+ private static final String TAG = "RESTRICTED_PREF";
+
+ @VisibleForTesting String KEY_RESTRICTED_PREF = "restricted_pref";
+ @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
+
+ public RestrictedPreferenceController(Context context, int uid, String packageName) {
+ super(context);
+ mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+
+ if (!mBatteryOptimizeUtils.isValidPackageName()) {
+ Log.d(TAG, "invalid package name, disable pref");
+ preference.setEnabled(false);
+ return;
+ } else {
+ preference.setEnabled(true);
+ }
+
+ if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
+ Log.d(TAG, "is system or default app, disable pref");
+ ((RadioButtonPreference) preference).setChecked(false);
+ preference.setEnabled(false);
+ } else if (mBatteryOptimizeUtils.getAppUsageState() == RESTRICTED) {
+ Log.d(TAG, "is restricted states");
+ ((RadioButtonPreference) preference).setChecked(true);
+ } else {
+ ((RadioButtonPreference) preference).setChecked(false);
+ }
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_RESTRICTED_PREF;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!KEY_RESTRICTED_PREF.equals(preference.getKey())) {
+ return false;
+ }
+
+ mBatteryOptimizeUtils.setAppUsageState(RESTRICTED);
+ Log.d(TAG, "Set restricted");
+ return true;
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java b/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
new file mode 100644
index 0000000..36141c5
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.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 static com.android.settings.fuelgauge.BatteryOptimizeUtils.AppUsageState.UNRESTRICTED;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+public class UnrestrictedPreferenceController extends AbstractPreferenceController
+ implements PreferenceControllerMixin {
+
+ private static final String TAG = "UNRESTRICTED_PREF";
+
+ @VisibleForTesting String KEY_UNRESTRICTED_PREF = "unrestricted_pref";
+ @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
+
+ public UnrestrictedPreferenceController(Context context, int uid, String packageName) {
+ super(context);
+ mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+
+ if (!mBatteryOptimizeUtils.isValidPackageName()) {
+ Log.d(TAG, "invalid package name, disable pref");
+ preference.setEnabled(false);
+ return;
+ } else {
+ preference.setEnabled(true);
+ }
+
+ if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
+ Log.d(TAG, "is system or default app, unrestricted states only");
+ ((RadioButtonPreference) preference).setChecked(true);
+ } else if (mBatteryOptimizeUtils.getAppUsageState() == UNRESTRICTED) {
+ Log.d(TAG, "is unrestricted states");
+ ((RadioButtonPreference) preference).setChecked(true);
+ } else {
+ ((RadioButtonPreference) preference).setChecked(false);
+ }
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_UNRESTRICTED_PREF;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!KEY_UNRESTRICTED_PREF.equals(preference.getKey())) {
+ return false;
+ }
+
+ mBatteryOptimizeUtils.setAppUsageState(UNRESTRICTED);
+ Log.d(TAG, "Set unrestricted");
+ return true;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java
index 197fdff..c5ea21f 100644
--- a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java
@@ -34,7 +34,6 @@
import com.google.common.collect.ImmutableList;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@@ -80,7 +79,6 @@
}
@Test
- @Ignore
public void getPreferenceSummary_appOpNotAllowed_returnsNotAllowed() {
shadowOf(mUserManager).addUser(
PERSONAL_PROFILE_ID, "personal-profile"/* name */, 0/* flags */);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index 7f76c70..820607f 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doAnswer;
@@ -58,6 +59,7 @@
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.widget.LayoutPreference;
+import com.android.settingslib.widget.RadioButtonPreference;
import org.junit.After;
import org.junit.Before;
@@ -96,6 +98,9 @@
private static final long PROCSTATE_TOP_TIME_US = PROCSTATE_TOP_TIME_MS * 1000;
private static final long PHONE_FOREGROUND_TIME_MS = 250 * 1000;
private static final long PHONE_BACKGROUND_TIME_MS = 0;
+ private static final String KEY_PREF_UNRESTRICTED = "unrestricted_pref";
+ private static final String KEY_PREF_OPTIMIZED = "optimized_pref";
+ private static final String KEY_PREF_RESTRICTED = "restricted_pref";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private FragmentActivity mActivity;
@@ -121,9 +126,15 @@
private BatteryStats.Timer mForegroundActivityTimer;
@Mock
private BatteryUtils mBatteryUtils;
+ @Mock
+ private BatteryOptimizeUtils mBatteryOptimizeUtils;
private Context mContext;
private Preference mForegroundPreference;
private Preference mBackgroundPreference;
+ private Preference mFooterPreference;
+ private RadioButtonPreference mRestrictedPreference;
+ private RadioButtonPreference mOptimizePreference;
+ private RadioButtonPreference mUnrestrictedPreference;
private AdvancedPowerUsageDetail mFragment;
private SettingsActivity mTestActivity;
@@ -170,6 +181,7 @@
mFragment.mHeaderPreference = mHeaderPreference;
mFragment.mState = mState;
mFragment.mBatteryUtils = new BatteryUtils(RuntimeEnvironment.application);
+ mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
mAppEntry.info = mock(ApplicationInfo.class);
mTestActivity = spy(new SettingsActivity());
@@ -194,8 +206,16 @@
mForegroundPreference = new Preference(mContext);
mBackgroundPreference = new Preference(mContext);
+ mFooterPreference = new Preference(mContext);
+ mRestrictedPreference = new RadioButtonPreference(mContext);
+ mOptimizePreference = new RadioButtonPreference(mContext);
+ mUnrestrictedPreference = new RadioButtonPreference(mContext);
mFragment.mForegroundPreference = mForegroundPreference;
mFragment.mBackgroundPreference = mBackgroundPreference;
+ mFragment.mFooterPreference = mFooterPreference;
+ mFragment.mRestrictedPreference = mRestrictedPreference;
+ mFragment.mOptimizePreference = mOptimizePreference;
+ mFragment.mUnrestrictedPreference = mUnrestrictedPreference;
}
@After
@@ -352,4 +372,48 @@
assertThat(mForegroundPreference.getSummary().toString()).isEqualTo("Used for 0 min");
assertThat(mBackgroundPreference.getSummary().toString()).isEqualTo("Active for 0 min");
}
+
+ @Test
+ public void testInitPreference_isValidPackageName_hasCorrectString() {
+ when(mBatteryOptimizeUtils.isValidPackageName()).thenReturn(false);
+
+ mFragment.initPreference();
+
+ assertThat(mFooterPreference.getTitle().toString())
+ .isEqualTo("This app requires Optimized battery usage.");
+ }
+
+ @Test
+ public void testInitPreference_isSystemOrDefaultApp_hasCorrectString() {
+ when(mBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+ when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+
+ mFragment.initPreference();
+
+ assertThat(mFooterPreference.getTitle()
+ .toString()).isEqualTo("This app requires Unrestricted battery usage.");
+ }
+
+ @Test
+ public void testInitPreference_hasCorrectString() {
+ when(mBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+ when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
+
+ mFragment.initPreference();
+
+ assertThat(mFooterPreference.getTitle().toString())
+ .isEqualTo("Changing how an app uses your battery can affect its performance.");
+ }
+
+ @Test
+ public void testOnRadioButtonClicked_clickOptimizePref_optimizePreferenceChecked() {
+ mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
+ mRestrictedPreference.setKey(KEY_PREF_RESTRICTED);
+ mUnrestrictedPreference.setKey(KEY_PREF_UNRESTRICTED);
+ mFragment.onRadioButtonClicked(mOptimizePreference);
+
+ assertThat(mOptimizePreference.isChecked()).isTrue();
+ assertThat(mRestrictedPreference.isChecked()).isFalse();
+ assertThat(mUnrestrictedPreference.isChecked()).isFalse();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java
new file mode 100644
index 0000000..89d66be
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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.android.settings.fuelgauge.BatteryOptimizeUtils.AppUsageState.OPTIMIZED;
+import static com.android.settings.fuelgauge.BatteryOptimizeUtils.AppUsageState.RESTRICTED;
+import static com.android.settings.fuelgauge.BatteryOptimizeUtils.AppUsageState.UNRESTRICTED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+
+import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
+
+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 class BatteryOptimizeUtilsTest {
+
+ private static final int UID = 12345;
+ private static final String PACKAGE_NAME = "com.android.app";
+
+ @Mock BatteryUtils mockBatteryUtils;
+ @Mock AppOpsManager mockAppOpsManager;
+ @Mock PowerAllowlistBackend mockBackend;
+
+ private Context mContext;
+ private BatteryOptimizeUtils mBatteryOptimizeUtils;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(mContext, UID, PACKAGE_NAME));
+ mBatteryOptimizeUtils.mAppOpsManager = mockAppOpsManager;
+ mBatteryOptimizeUtils.mBatteryUtils = mockBatteryUtils;
+ mBatteryOptimizeUtils.mPowerAllowListBackend = mockBackend;
+ }
+
+ @Test
+ public void testGetAppUsageState_returnRestricted() {
+ when(mockBackend.isAllowlisted(anyString())).thenReturn(false);
+ when(mockAppOpsManager.checkOpNoThrow(anyInt(), anyInt(), anyString()))
+ .thenReturn(AppOpsManager.MODE_IGNORED);
+
+ assertThat(mBatteryOptimizeUtils.getAppUsageState()).isEqualTo(RESTRICTED);
+ }
+
+ @Test
+ public void testGetAppUsageState_returnUnrestricted() {
+ when(mockBackend.isAllowlisted(anyString())).thenReturn(true);
+ when(mockAppOpsManager.checkOpNoThrow(anyInt(), anyInt(), anyString()))
+ .thenReturn(AppOpsManager.MODE_ALLOWED);
+
+ assertThat(mBatteryOptimizeUtils.getAppUsageState()).isEqualTo(UNRESTRICTED);
+ }
+
+ @Test
+ public void testGetAppUsageState_returnOptimized() {
+ when(mockBackend.isAllowlisted(anyString())).thenReturn(false);
+ when(mockAppOpsManager.checkOpNoThrow(anyInt(), anyInt(), anyString()))
+ .thenReturn(AppOpsManager.MODE_ALLOWED);
+
+ assertThat(mBatteryOptimizeUtils.getAppUsageState()).isEqualTo(OPTIMIZED);
+ }
+
+ @Test
+ public void testIsSystemOrDefaultApp_isSystemOrDefaultApp_returnTrue() {
+ when(mockBackend.isAllowlisted(anyString())).thenReturn(true);
+ when(mockBackend.isDefaultActiveApp(anyString())).thenReturn(true);
+
+ assertThat(mBatteryOptimizeUtils.isSystemOrDefaultApp()).isTrue();
+ }
+
+ @Test
+ public void testIsSystemOrDefaultApp_notSystemOrDefaultApp_returnFalse() {
+ assertThat(mBatteryOptimizeUtils.isSystemOrDefaultApp()).isFalse();
+ }
+
+ @Test
+ public void testIsValidPackageName_InvalidPackageName_returnFalse() {
+ final BatteryOptimizeUtils testBatteryOptimizeUtils =
+ new BatteryOptimizeUtils(mContext, UID, null);
+
+ assertThat(testBatteryOptimizeUtils.isValidPackageName()).isFalse();
+ }
+
+ @Test
+ public void testIsValidPackageName_validPackageName_returnTrue() {
+ assertThat(mBatteryOptimizeUtils.isValidPackageName()).isTrue();
+ }
+
+ @Test
+ public void testSetAppUsageState_Restricted_verifyAction() {
+ mBatteryOptimizeUtils.setAppUsageState(RESTRICTED);
+
+ verify(mockBatteryUtils).setForceAppStandby(UID,
+ PACKAGE_NAME, AppOpsManager.MODE_IGNORED);
+ verify(mockBackend).removeApp(PACKAGE_NAME);
+ }
+
+ @Test
+ public void testSetAppUsageState_Unrestricted_verifyAction() {
+ mBatteryOptimizeUtils.setAppUsageState(UNRESTRICTED);
+
+ verify(mockBatteryUtils).setForceAppStandby(UID,
+ PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
+ verify(mockBackend).addApp(PACKAGE_NAME);
+ }
+
+ @Test
+ public void testSetAppUsageState_Optimized_verifyAction() {
+ mBatteryOptimizeUtils.setAppUsageState(OPTIMIZED);
+
+ verify(mockBatteryUtils).setForceAppStandby(UID,
+ PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
+ verify(mockBackend).removeApp(PACKAGE_NAME);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
new file mode 100644
index 0000000..874618d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import com.android.settingslib.widget.RadioButtonPreference;
+
+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 class OptimizedPreferenceControllerTest {
+ private static final int UID = 12345;
+ private static final String PACKAGE_NAME = "com.android.app";
+
+ private OptimizedPreferenceController mController;
+ private RadioButtonPreference mPreference;
+
+ @Mock BatteryOptimizeUtils mockBatteryOptimizeUtils;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mController = new OptimizedPreferenceController(
+ RuntimeEnvironment.application, UID, PACKAGE_NAME);
+ mPreference = new RadioButtonPreference(RuntimeEnvironment.application);
+ mController.mBatteryOptimizeUtils = mockBatteryOptimizeUtils;
+ }
+
+ @Test
+ public void testUpdateState_invalidPackage_prefEnabled() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(false);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isEnabled()).isTrue();
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+ when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isFalse();
+ assertThat(mPreference.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void testUpdateState_isOptimizedStates_prefChecked() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+ when(mockBatteryOptimizeUtils.getAppUsageState()).thenReturn(
+ BatteryOptimizeUtils.AppUsageState.OPTIMIZED);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void testUpdateState_prefUnchecked() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isFalse();
+ }
+
+ @Test
+ public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
+ mPreference.setKey(mController.KEY_OPTIMIZED_PREF);
+ mController.handlePreferenceTreeClick(mPreference);
+
+ verify(mockBatteryOptimizeUtils).setAppUsageState(
+ BatteryOptimizeUtils.AppUsageState.OPTIMIZED);
+ }
+
+ @Test
+ public void testHandlePreferenceTreeClick_incorrectPrefKey_noAction() {
+ mController.handlePreferenceTreeClick(mPreference);
+
+ verifyZeroInteractions(mockBatteryOptimizeUtils);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java
new file mode 100644
index 0000000..2e17404
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import com.android.settingslib.widget.RadioButtonPreference;
+
+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 class RestrictedPreferenceControllerTest {
+ private static final int UID = 12345;
+ private static final String PACKAGE_NAME = "com.android.app";
+
+ private RestrictedPreferenceController mController;
+ private RadioButtonPreference mPreference;
+
+ @Mock BatteryOptimizeUtils mockBatteryOptimizeUtils;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mController = new RestrictedPreferenceController(
+ RuntimeEnvironment.application, UID, PACKAGE_NAME);
+ mPreference = new RadioButtonPreference(RuntimeEnvironment.application);
+ mController.mBatteryOptimizeUtils = mockBatteryOptimizeUtils;
+ }
+
+ @Test
+ public void testUpdateState_isValidPackage_prefEnabled() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void testUpdateState_invalidPackage_prefDisabled() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(false);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void testUpdateState_isSystemOrDefaultApp_prefChecked() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+ when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isFalse();
+ assertThat(mPreference.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void testUpdateState_isRestrictedStates_prefChecked() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+ when(mockBatteryOptimizeUtils.getAppUsageState()).thenReturn(
+ BatteryOptimizeUtils.AppUsageState.RESTRICTED);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void testUpdateState_prefUnchecked() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isFalse();
+ }
+
+ @Test
+ public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
+ mPreference.setKey(mController.KEY_RESTRICTED_PREF);
+ mController.handlePreferenceTreeClick(mPreference);
+
+ verify(mockBatteryOptimizeUtils).setAppUsageState(
+ BatteryOptimizeUtils.AppUsageState.RESTRICTED);
+ }
+
+ @Test
+ public void testHandlePreferenceTreeClick_incorrectPrefKey_noAction() {
+ mController.handlePreferenceTreeClick(mPreference);
+
+ verifyZeroInteractions(mockBatteryOptimizeUtils);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
new file mode 100644
index 0000000..63cf760
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import com.android.settingslib.widget.RadioButtonPreference;
+
+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 class UnrestrictedPreferenceControllerTest {
+ private static final int UID = 12345;
+ private static final String PACKAGE_NAME = "com.android.app";
+
+ private UnrestrictedPreferenceController mController;
+ private RadioButtonPreference mPreference;
+
+ @Mock BatteryOptimizeUtils mockBatteryOptimizeUtils;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mController = new UnrestrictedPreferenceController(
+ RuntimeEnvironment.application, UID, PACKAGE_NAME);
+ mPreference = new RadioButtonPreference(RuntimeEnvironment.application);
+ mController.mBatteryOptimizeUtils = mockBatteryOptimizeUtils;
+ }
+
+ @Test
+ public void testUpdateState_isValidPackage_prefEnabled() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void testUpdateState_invalidPackage_prefDisabled() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(false);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void testUpdateState_isSystemOrDefaultApp_prefChecked() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+ when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void testUpdateState_isUnrestrictedStates_prefChecked() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+ when(mockBatteryOptimizeUtils.getAppUsageState()).thenReturn(
+ BatteryOptimizeUtils.AppUsageState.UNRESTRICTED);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void testUpdateState_prefUnchecked() {
+ when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isFalse();
+ }
+
+ @Test
+ public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
+ mPreference.setKey(mController.KEY_UNRESTRICTED_PREF);
+ mController.handlePreferenceTreeClick(mPreference);
+
+ verify(mockBatteryOptimizeUtils).setAppUsageState(
+ BatteryOptimizeUtils.AppUsageState.UNRESTRICTED);
+ }
+
+ @Test
+ public void testHandlePreferenceTreeClick_incorrectPrefKey_noAction() {
+ mController.handlePreferenceTreeClick(mPreference);
+
+ verifyZeroInteractions(mockBatteryOptimizeUtils);
+ }
+}