Revamp the battery detail page for each app

1. Move preferences to new postion
2. Change background activity pref from SwitchPreference to
Preference and update the controller

Bug: 72227981
Test: RunSettingsRoboTests
Change-Id: Ib18ac7523c24d19754c37ab8ac527095d9ced49c
This commit is contained in:
jackqdyulei
2018-01-19 17:32:23 -08:00
parent 35fc0a9a9b
commit 29002aacb0
5 changed files with 77 additions and 86 deletions

View File

@@ -4719,7 +4719,7 @@
<string name="power_charge_remaining"><xliff:g id="until_charged">%1$s</xliff:g> to charge</string> <string name="power_charge_remaining"><xliff:g id="until_charged">%1$s</xliff:g> to charge</string>
<!-- Title for the background activity setting, which allows a user to control whether an app can run in the background [CHAR_LIMIT=40] --> <!-- Title for the background activity setting, which allows a user to control whether an app can run in the background [CHAR_LIMIT=40] -->
<string name="background_activity_title">Background activity</string> <string name="background_activity_title">Restricted</string>
<!-- Summary for the background activity [CHAR_LIMIT=120] --> <!-- Summary for the background activity [CHAR_LIMIT=120] -->
<string name="background_activity_summary">Allow the app to run in the background</string> <string name="background_activity_summary">Allow the app to run in the background</string>
<!-- Summary for the background activity when it is on [CHAR_LIMIT=120] --> <!-- Summary for the background activity when it is on [CHAR_LIMIT=120] -->
@@ -7602,6 +7602,11 @@
<!-- Button label to say no to the question of whether to require PIN/password/pattern to start your device. [CHAR LIMIT=20] --> <!-- Button label to say no to the question of whether to require PIN/password/pattern to start your device. [CHAR LIMIT=20] -->
<string name="encryption_interstitial_no">No</string> <string name="encryption_interstitial_no">No</string>
<!-- Label to say yes to the question of whether app is restricted. [CHAR LIMIT=20] -->
<string name="restricted_true_label">Yes</string>
<!-- Label to say no to the question of whether app is restricted. [CHAR LIMIT=20] -->
<string name="restricted_false_label">No</string>
<!-- Title for encryption dialog that disables TalkBack. [CHAR_LIMIT=25] --> <!-- Title for encryption dialog that disables TalkBack. [CHAR_LIMIT=25] -->
<string name="encrypt_talkback_dialog_require_pin">Require PIN?</string> <string name="encrypt_talkback_dialog_require_pin">Require PIN?</string>

View File

@@ -27,6 +27,22 @@
android:key="action_buttons" android:key="action_buttons"
android:order="-9999"/> android:order="-9999"/>
<PreferenceCategory
android:title="@string/battery_detail_manage_title">
<Preference
android:key="background_activity"
android:title="@string/background_activity_title"
android:selectable="true"/>
<Preference
android:key="battery_optimization"
android:title="@string/high_power_apps"
android:summary="@string/high_power_off"
android:selectable="true"/>
</PreferenceCategory>
<Preference <Preference
android:key="high_usage" android:key="high_usage"
android:icon="@drawable/ic_battery_alert_24dp" android:icon="@drawable/ic_battery_alert_24dp"
@@ -52,20 +68,4 @@
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory
android:title="@string/battery_detail_manage_title">
<SwitchPreference
android:key="background_activity"
android:title="@string/background_activity_title"
android:selectable="true"/>
<Preference
android:key="battery_optimization"
android:title="@string/high_power_apps"
android:summary="@string/high_power_off"
android:selectable="true"/>
</PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>

View File

@@ -374,7 +374,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
@Override @Override
public void onLimitBackgroundActivity() { public void onLimitBackgroundActivity() {
mBackgroundActivityPreferenceController.setUnchecked( mBackgroundActivityPreferenceController.setRestricted(
findPreference(mBackgroundActivityPreferenceController.getPreferenceKey())); findPreference(mBackgroundActivityPreferenceController.getPreferenceKey()));
} }
} }

View File

@@ -43,12 +43,12 @@ import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
* Controller to control whether an app can run in the background * Controller to control whether an app can run in the background
*/ */
public class BackgroundActivityPreferenceController extends AbstractPreferenceController public class BackgroundActivityPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener { implements PreferenceControllerMixin {
private static final String TAG = "BgActivityPrefContr"; private static final String TAG = "BgActivityPrefContr";
private static final String KEY_BACKGROUND_ACTIVITY = "background_activity"; @VisibleForTesting
static final String KEY_BACKGROUND_ACTIVITY = "background_activity";
private final PackageManager mPackageManager;
private final AppOpsManager mAppOpsManager; private final AppOpsManager mAppOpsManager;
private final UserManager mUserManager; private final UserManager mUserManager;
private final int mUid; private final int mUid;
@@ -70,7 +70,6 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
int uid, String packageName, PowerWhitelistBackend backend) { int uid, String packageName, PowerWhitelistBackend backend) {
super(context); super(context);
mPowerWhitelistBackend = backend; mPowerWhitelistBackend = backend;
mPackageManager = context.getPackageManager();
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mDpm = new DevicePolicyManagerWrapper( mDpm = new DevicePolicyManagerWrapper(
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE)); (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE));
@@ -86,11 +85,6 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
final int mode = mAppOpsManager final int mode = mAppOpsManager
.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage); .checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage);
final boolean whitelisted = mPowerWhitelistBackend.isWhitelisted(mTargetPackage); final boolean whitelisted = mPowerWhitelistBackend.isWhitelisted(mTargetPackage);
// Set checked or not before we may set it disabled
if (mode != AppOpsManager.MODE_ERRORED) {
final boolean checked = whitelisted || mode != AppOpsManager.MODE_IGNORED;
((SwitchPreference) preference).setChecked(checked);
}
if (whitelisted || mode == AppOpsManager.MODE_ERRORED if (whitelisted || mode == AppOpsManager.MODE_ERRORED
|| Utils.isProfileOrDeviceOwner(mUserManager, mDpm, mTargetPackage)) { || Utils.isProfileOrDeviceOwner(mUserManager, mDpm, mTargetPackage)) {
preference.setEnabled(false); preference.setEnabled(false);
@@ -109,9 +103,8 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
* Called from the warning dialog, if the user decides to go ahead and disable background * Called from the warning dialog, if the user decides to go ahead and disable background
* activity for this package * activity for this package
*/ */
public void setUnchecked(Preference preference) { public void setRestricted(Preference preference) {
mBatteryUtils.setForceAppStandby(mUid, mTargetPackage, AppOpsManager.MODE_IGNORED); mBatteryUtils.setForceAppStandby(mUid, mTargetPackage, AppOpsManager.MODE_IGNORED);
((SwitchPreference) preference).setChecked(false);
updateSummary(preference); updateSummary(preference);
} }
@@ -121,17 +114,21 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
} }
@Override @Override
public boolean onPreferenceChange(Preference preference, Object newValue) { public boolean handlePreferenceTreeClick(Preference preference) {
final boolean switchOn = (Boolean) newValue; if (KEY_BACKGROUND_ACTIVITY.equals(preference.getKey())) {
if (!switchOn) { final int mode = mAppOpsManager
final WarningDialogFragment dialogFragment = new WarningDialogFragment(); .checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage);
dialogFragment.setTargetFragment(mFragment, 0); final boolean restricted = mode == AppOpsManager.MODE_IGNORED;
dialogFragment.show(mFragment.getFragmentManager(), TAG); if (!restricted) {
return false; showDialog();
return false;
}
mBatteryUtils.setForceAppStandby(mUid, mTargetPackage, AppOpsManager.MODE_ALLOWED);
updateSummary(preference);
return true;
} }
mBatteryUtils.setForceAppStandby(mUid, mTargetPackage, AppOpsManager.MODE_ALLOWED);
updateSummary(preference); return false;
return true;
} }
@VisibleForTesting @VisibleForTesting
@@ -146,12 +143,19 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
if (mode == AppOpsManager.MODE_ERRORED) { if (mode == AppOpsManager.MODE_ERRORED) {
preference.setSummary(R.string.background_activity_summary_disabled); preference.setSummary(R.string.background_activity_summary_disabled);
} else { } else {
final boolean checked = mode != AppOpsManager.MODE_IGNORED; final boolean restricted = mode == AppOpsManager.MODE_IGNORED;
preference.setSummary(checked ? R.string.background_activity_summary_on preference.setSummary(restricted ? R.string.restricted_true_label
: R.string.background_activity_summary_off); : R.string.restricted_false_label);
} }
} }
@VisibleForTesting
void showDialog() {
final WarningDialogFragment dialogFragment = new WarningDialogFragment();
dialogFragment.setTargetFragment(mFragment, 0 /* requestCode */);
dialogFragment.show(mFragment.getFragmentManager(), TAG);
}
interface WarningConfirmationListener { interface WarningConfirmationListener {
void onLimitBackgroundActivity(); void onLimitBackgroundActivity();
} }

View File

@@ -22,6 +22,7 @@ import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -38,6 +39,7 @@ import android.content.pm.PackageManager;
import android.os.Build; import android.os.Build;
import android.os.UserManager; import android.os.UserManager;
import android.support.v14.preference.SwitchPreference; import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.widget.Button; import android.widget.Button;
import com.android.settings.R; import com.android.settings.R;
@@ -92,12 +94,12 @@ public class BackgroundActivityPreferenceControllerTest {
private DevicePolicyManager mDevicePolicyManager; private DevicePolicyManager mDevicePolicyManager;
@Mock @Mock
private DevicePolicyManagerWrapper mDevicePolicyManagerWrapper; private DevicePolicyManagerWrapper mDevicePolicyManagerWrapper;
@Mock @Mock(answer = Answers.RETURNS_DEEP_STUBS)
private AdvancedPowerUsageDetail mFragment; private AdvancedPowerUsageDetail mFragment;
@Mock @Mock
private PowerWhitelistBackend mPowerWhitelistBackend; private PowerWhitelistBackend mPowerWhitelistBackend;
private BackgroundActivityPreferenceController mController; private BackgroundActivityPreferenceController mController;
private SwitchPreference mPreference; private Preference mPreference;
private Context mShadowContext; private Context mShadowContext;
private BatteryUtils mBatteryUtils; private BatteryUtils mBatteryUtils;
@@ -125,7 +127,8 @@ public class BackgroundActivityPreferenceControllerTest {
mBatteryUtils = spy(new BatteryUtils(mShadowContext)); mBatteryUtils = spy(new BatteryUtils(mShadowContext));
doNothing().when(mBatteryUtils).setForceAppStandby(anyInt(), anyString(), anyInt()); doNothing().when(mBatteryUtils).setForceAppStandby(anyInt(), anyString(), anyInt());
mPreference = new SwitchPreference(mShadowContext); mPreference = new Preference(mShadowContext);
mPreference.setKey(BackgroundActivityPreferenceController.KEY_BACKGROUND_ACTIVITY);
mController = spy(new BackgroundActivityPreferenceController( mController = spy(new BackgroundActivityPreferenceController(
mContext, mFragment, UID_LOW_SDK, LOW_SDK_PACKAGE, mPowerWhitelistBackend)); mContext, mFragment, UID_LOW_SDK, LOW_SDK_PACKAGE, mPowerWhitelistBackend));
mController.mDpm = mDevicePolicyManagerWrapper; mController.mDpm = mDevicePolicyManagerWrapper;
@@ -133,49 +136,33 @@ public class BackgroundActivityPreferenceControllerTest {
} }
@Test @Test
public void testOnPreferenceChange_TurnOnCheck_MethodInvoked() { public void testHandlePreferenceTreeClick_restrictApp_showDialog() {
mController.onPreferenceChange(mPreference, true); doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager).checkOpNoThrow(anyInt(),
anyInt(), anyString());
mController.handlePreferenceTreeClick(mPreference);
verify(mController).showDialog();
}
@Test
public void testHandlePreferenceTreeClick_unRestrictApp_setModeAllowed() {
doReturn(AppOpsManager.MODE_IGNORED).when(mAppOpsManager).checkOpNoThrow(anyInt(),
anyInt(), anyString());
mController.handlePreferenceTreeClick(mPreference);
verify(mBatteryUtils).setForceAppStandby(UID_LOW_SDK, LOW_SDK_PACKAGE, verify(mBatteryUtils).setForceAppStandby(UID_LOW_SDK, LOW_SDK_PACKAGE,
AppOpsManager.MODE_ALLOWED); AppOpsManager.MODE_ALLOWED);
assertThat(mPreference.getSummary())
.isEqualTo(mShadowContext.getText(R.string.background_activity_summary_on));
} }
@Test @Test
public void testOnPreferenceChange_TurnOnCheckHighSDK_MethodInvoked() { public void testUpdateState_noError_setEnabled() {
mController = new BackgroundActivityPreferenceController(mContext, mFragment, UID_HIGH_SDK,
HIGH_SDK_PACKAGE, mPowerWhitelistBackend);
mController.mBatteryUtils = mBatteryUtils;
mController.onPreferenceChange(mPreference, true);
verify(mBatteryUtils).setForceAppStandby(UID_HIGH_SDK, HIGH_SDK_PACKAGE,
AppOpsManager.MODE_ALLOWED);
assertThat(mPreference.getSummary())
.isEqualTo(mShadowContext.getText(R.string.background_activity_summary_on));
}
@Test
public void testUpdateState_CheckOn_SetCheckedTrue() {
when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK, when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED); LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED);
mController.updateState(mPreference); mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isTrue();
assertThat(mPreference.isEnabled()).isTrue();
verify(mController).updateSummary(mPreference);
}
@Test
public void testUpdateState_CheckOff_SetCheckedFalse() {
when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_IGNORED);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isFalse();
assertThat(mPreference.isEnabled()).isTrue(); assertThat(mPreference.isEnabled()).isTrue();
verify(mController).updateSummary(mPreference); verify(mController).updateSummary(mPreference);
} }
@@ -184,7 +171,6 @@ public class BackgroundActivityPreferenceControllerTest {
public void testUpdateState_whitelisted() { public void testUpdateState_whitelisted() {
when(mPowerWhitelistBackend.isWhitelisted(LOW_SDK_PACKAGE)).thenReturn(true); when(mPowerWhitelistBackend.isWhitelisted(LOW_SDK_PACKAGE)).thenReturn(true);
mController.updateState(mPreference); mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isTrue();
assertThat(mPreference.isEnabled()).isFalse(); assertThat(mPreference.isEnabled()).isFalse();
assertThat(mPreference.getSummary()).isEqualTo( assertThat(mPreference.getSummary()).isEqualTo(
mShadowContext.getText(R.string.background_activity_summary_whitelisted)); mShadowContext.getText(R.string.background_activity_summary_whitelisted));
@@ -202,27 +188,23 @@ public class BackgroundActivityPreferenceControllerTest {
} }
@Test @Test
public void testUpdateSummary_modeDefault_showSummaryOn() { public void testUpdateSummary_modeDefault_showNotRestricted() {
when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK, when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_DEFAULT); LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_DEFAULT);
final CharSequence expectedSummary = mShadowContext.getText(
R.string.background_activity_summary_on);
mController.updateSummary(mPreference); mController.updateSummary(mPreference);
assertThat(mPreference.getSummary()).isEqualTo(expectedSummary); assertThat(mPreference.getSummary()).isEqualTo("No");
} }
@Test @Test
public void testUpdateSummary_modeIgnored_showSummaryOff() { public void testUpdateSummary_modeIgnored_showRestricted() {
when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK, when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_IGNORED); LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_IGNORED);
final CharSequence expectedSummary = mShadowContext.getText(
R.string.background_activity_summary_off);
mController.updateSummary(mPreference); mController.updateSummary(mPreference);
assertThat(mPreference.getSummary()).isEqualTo(expectedSummary); assertThat(mPreference.getSummary()).isEqualTo("Yes");
} }
@Test @Test