Loading src/com/android/settings/fuelgauge/RestrictedAppDetails.java +45 −9 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.settings.fuelgauge; import android.app.AppOpsManager; import android.app.Fragment; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; Loading @@ -31,12 +29,16 @@ import android.util.IconDrawableFactory; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.Utils; import com.android.settings.core.InstrumentedPreferenceFragment; import com.android.settings.core.SubSettingLauncher; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.fuelgauge.batterytip.AppInfo; import com.android.settings.fuelgauge.batterytip.BatteryTipDialogFragment; import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController; import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip; import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip; import com.android.settings.widget.AppCheckBoxPreference; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.widget.FooterPreferenceMixin; Loading @@ -46,7 +48,8 @@ import java.util.List; /** * Fragment to show a list of anomaly apps, where user could handle these anomalies */ public class RestrictedAppDetails extends DashboardFragment { public class RestrictedAppDetails extends DashboardFragment implements BatteryTipPreferenceController.BatteryTipListener { public static final String TAG = "RestrictedAppDetails"; Loading Loading @@ -145,12 +148,14 @@ public class RestrictedAppDetails extends DashboardFragment { Utils.getBadgedIcon(mIconDrawableFactory, mPackageManager, appInfo.packageName, UserHandle.getUserId(appInfo.uid))); checkBoxPreference.setKey(getKeyFromAppInfo(appInfo)); checkBoxPreference.setOnPreferenceChangeListener((pref, value) -> { // change the toggle final int mode = (Boolean) value ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED; mBatteryUtils.setForceAppStandby(appInfo.uid, appInfo.packageName, mode); return true; final BatteryTipDialogFragment fragment = createDialogFragment(appInfo, (Boolean) value); fragment.setTargetFragment(this, 0 /* requestCode */); fragment.show(getFragmentManager(), TAG); return false; }); mRestrictedAppListGroup.addPreference(checkBoxPreference); } catch (PackageManager.NameNotFoundException e) { Loading @@ -159,4 +164,35 @@ public class RestrictedAppDetails extends DashboardFragment { } } @Override public void onBatteryTipHandled(BatteryTip batteryTip) { final AppInfo appInfo; final boolean isRestricted = batteryTip instanceof RestrictAppTip; if (isRestricted) { appInfo = ((RestrictAppTip) batteryTip).getRestrictAppList().get(0); } else { appInfo = ((UnrestrictAppTip) batteryTip).getUnrestrictAppInfo(); } CheckBoxPreference preference = (CheckBoxPreference) mRestrictedAppListGroup .findPreference(getKeyFromAppInfo(appInfo)); if (preference != null) { preference.setChecked(isRestricted); } } @VisibleForTesting BatteryTipDialogFragment createDialogFragment(AppInfo appInfo, boolean toRestrict) { final BatteryTip batteryTip = toRestrict ? new RestrictAppTip(BatteryTip.StateType.NEW, appInfo) : new UnrestrictAppTip(BatteryTip.StateType.NEW, appInfo); return BatteryTipDialogFragment.newInstance( batteryTip, getMetricsCategory()); } @VisibleForTesting String getKeyFromAppInfo(AppInfo appInfo) { return appInfo.uid + "," + appInfo.packageName; } } src/com/android/settings/fuelgauge/batterytip/tips/UnrestrictAppTip.java +4 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,10 @@ public class UnrestrictAppTip extends BatteryTip { // Do nothing } public AppInfo getUnrestrictAppInfo() { return mAppInfo; } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); Loading tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java +67 −7 Original line number Diff line number Diff line Loading @@ -21,7 +21,9 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.robolectric.Shadows.shadowOf; import android.app.AlertDialog; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; Loading @@ -38,6 +40,11 @@ import android.widget.CheckBox; import com.android.settings.SettingsActivity; import com.android.settings.core.InstrumentedPreferenceFragment; import com.android.settings.fuelgauge.batterytip.AppInfo; import com.android.settings.fuelgauge.batterytip.BatteryTipDialogFragment; import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip; import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip; import com.android.settings.testutils.SettingsRobolectricTestRunner; import org.junit.Before; import org.junit.Test; Loading @@ -46,13 +53,15 @@ import org.mockito.Answers; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.shadows.ShadowAlertDialog; import org.robolectric.shadows.ShadowDialog; import org.robolectric.util.FragmentTestUtil; import java.util.ArrayList; import java.util.List; @RunWith(RobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class) public class RestrictedAppDetailsTest { private static final String PACKAGE_NAME = "com.android.app"; Loading @@ -60,20 +69,21 @@ public class RestrictedAppDetailsTest { private static final int UID = UserHandle.getUid(USER_ID, 234); private static final String APP_NAME = "app"; @Mock private PackageManager mPackageManager; @Mock private ApplicationInfo mApplicationInfo; @Mock private IconDrawableFactory mIconDrawableFactory; @Mock(answer = Answers.RETURNS_DEEP_STUBS) private PreferenceManager mPreferenceManager; @Mock private InstrumentedPreferenceFragment mFragment; private PreferenceManager mPreferenceManager; private RestrictedAppDetails mRestrictedAppDetails; private Context mContext; private AppInfo mAppInfo; private Intent mIntent; private CheckBoxPreference mCheckBoxPreference; @Before public void setUp() { Loading @@ -86,8 +96,9 @@ public class RestrictedAppDetailsTest { .setUid(UID) .build(); mPreferenceManager = new PreferenceManager(mContext); doReturn(mPreferenceManager).when(mRestrictedAppDetails).getPreferenceManager(); doReturn(mContext).when(mPreferenceManager).getContext(); doReturn(mContext).when(mFragment).getContext(); mRestrictedAppDetails.mPackageManager = mPackageManager; mRestrictedAppDetails.mIconDrawableFactory = mIconDrawableFactory; Loading @@ -97,10 +108,13 @@ public class RestrictedAppDetailsTest { mRestrictedAppDetails.mBatteryUtils = spy(new BatteryUtils(mContext)); doReturn(mPreferenceManager).when( mRestrictedAppDetails.mRestrictedAppListGroup).getPreferenceManager(); mCheckBoxPreference = new CheckBoxPreference(mContext); mCheckBoxPreference.setKey(mRestrictedAppDetails.getKeyFromAppInfo(mAppInfo)); } @Test public void testRefreshUi_displayPreference() throws Exception { public void refreshUi_displayPreference() throws Exception { doReturn(mApplicationInfo).when(mPackageManager) .getApplicationInfoAsUser(PACKAGE_NAME, 0, USER_ID); doReturn(APP_NAME).when(mPackageManager).getApplicationLabel(mApplicationInfo); Loading @@ -117,7 +131,7 @@ public class RestrictedAppDetailsTest { } @Test public void testStartRestrictedAppDetails_startWithCorrectData() { public void startRestrictedAppDetails_startWithCorrectData() { final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); doAnswer(invocation -> { // Get the intent in which it has the app info bundle Loading @@ -135,4 +149,50 @@ public class RestrictedAppDetailsTest { RestrictedAppDetails.EXTRA_APP_INFO_LIST); assertThat(appInfos).containsExactly(mAppInfo); } @Test public void createDialogFragment_toRestrict_createRestrictDialog() { final BatteryTipDialogFragment dialogFragment = mRestrictedAppDetails.createDialogFragment( mAppInfo, true); FragmentTestUtil.startFragment(dialogFragment); final AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog(); ShadowAlertDialog shadowDialog = shadowOf(dialog); assertThat(shadowDialog.getTitle()).isEqualTo("Restrict app?"); } @Test public void createDialogFragment_toUnrestrict_createUnrestrictDialog() { final BatteryTipDialogFragment dialogFragment = mRestrictedAppDetails.createDialogFragment( mAppInfo, false); FragmentTestUtil.startFragment(dialogFragment); final AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog(); ShadowAlertDialog shadowDialog = shadowOf(dialog); assertThat(shadowDialog.getTitle()).isEqualTo("Remove restriction?"); } @Test public void onBatteryTipHandled_restrict_setChecked() { final RestrictAppTip restrictAppTip = new RestrictAppTip(BatteryTip.StateType.NEW, mAppInfo); mRestrictedAppDetails.mRestrictedAppListGroup.addPreference(mCheckBoxPreference); mRestrictedAppDetails.onBatteryTipHandled(restrictAppTip); assertThat(mCheckBoxPreference.isChecked()).isTrue(); } @Test public void onBatteryTipHandled_unrestrict_setUnchecked() { final UnrestrictAppTip unrestrictAppTip = new UnrestrictAppTip(BatteryTip.StateType.NEW, mAppInfo); mRestrictedAppDetails.mRestrictedAppListGroup.addPreference(mCheckBoxPreference); mRestrictedAppDetails.onBatteryTipHandled(unrestrictAppTip); assertThat(mCheckBoxPreference.isChecked()).isFalse(); } } Loading
src/com/android/settings/fuelgauge/RestrictedAppDetails.java +45 −9 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.settings.fuelgauge; import android.app.AppOpsManager; import android.app.Fragment; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; Loading @@ -31,12 +29,16 @@ import android.util.IconDrawableFactory; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.Utils; import com.android.settings.core.InstrumentedPreferenceFragment; import com.android.settings.core.SubSettingLauncher; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.fuelgauge.batterytip.AppInfo; import com.android.settings.fuelgauge.batterytip.BatteryTipDialogFragment; import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController; import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip; import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip; import com.android.settings.widget.AppCheckBoxPreference; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.widget.FooterPreferenceMixin; Loading @@ -46,7 +48,8 @@ import java.util.List; /** * Fragment to show a list of anomaly apps, where user could handle these anomalies */ public class RestrictedAppDetails extends DashboardFragment { public class RestrictedAppDetails extends DashboardFragment implements BatteryTipPreferenceController.BatteryTipListener { public static final String TAG = "RestrictedAppDetails"; Loading Loading @@ -145,12 +148,14 @@ public class RestrictedAppDetails extends DashboardFragment { Utils.getBadgedIcon(mIconDrawableFactory, mPackageManager, appInfo.packageName, UserHandle.getUserId(appInfo.uid))); checkBoxPreference.setKey(getKeyFromAppInfo(appInfo)); checkBoxPreference.setOnPreferenceChangeListener((pref, value) -> { // change the toggle final int mode = (Boolean) value ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED; mBatteryUtils.setForceAppStandby(appInfo.uid, appInfo.packageName, mode); return true; final BatteryTipDialogFragment fragment = createDialogFragment(appInfo, (Boolean) value); fragment.setTargetFragment(this, 0 /* requestCode */); fragment.show(getFragmentManager(), TAG); return false; }); mRestrictedAppListGroup.addPreference(checkBoxPreference); } catch (PackageManager.NameNotFoundException e) { Loading @@ -159,4 +164,35 @@ public class RestrictedAppDetails extends DashboardFragment { } } @Override public void onBatteryTipHandled(BatteryTip batteryTip) { final AppInfo appInfo; final boolean isRestricted = batteryTip instanceof RestrictAppTip; if (isRestricted) { appInfo = ((RestrictAppTip) batteryTip).getRestrictAppList().get(0); } else { appInfo = ((UnrestrictAppTip) batteryTip).getUnrestrictAppInfo(); } CheckBoxPreference preference = (CheckBoxPreference) mRestrictedAppListGroup .findPreference(getKeyFromAppInfo(appInfo)); if (preference != null) { preference.setChecked(isRestricted); } } @VisibleForTesting BatteryTipDialogFragment createDialogFragment(AppInfo appInfo, boolean toRestrict) { final BatteryTip batteryTip = toRestrict ? new RestrictAppTip(BatteryTip.StateType.NEW, appInfo) : new UnrestrictAppTip(BatteryTip.StateType.NEW, appInfo); return BatteryTipDialogFragment.newInstance( batteryTip, getMetricsCategory()); } @VisibleForTesting String getKeyFromAppInfo(AppInfo appInfo) { return appInfo.uid + "," + appInfo.packageName; } }
src/com/android/settings/fuelgauge/batterytip/tips/UnrestrictAppTip.java +4 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,10 @@ public class UnrestrictAppTip extends BatteryTip { // Do nothing } public AppInfo getUnrestrictAppInfo() { return mAppInfo; } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); Loading
tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java +67 −7 Original line number Diff line number Diff line Loading @@ -21,7 +21,9 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.robolectric.Shadows.shadowOf; import android.app.AlertDialog; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; Loading @@ -38,6 +40,11 @@ import android.widget.CheckBox; import com.android.settings.SettingsActivity; import com.android.settings.core.InstrumentedPreferenceFragment; import com.android.settings.fuelgauge.batterytip.AppInfo; import com.android.settings.fuelgauge.batterytip.BatteryTipDialogFragment; import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip; import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip; import com.android.settings.testutils.SettingsRobolectricTestRunner; import org.junit.Before; import org.junit.Test; Loading @@ -46,13 +53,15 @@ import org.mockito.Answers; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.shadows.ShadowAlertDialog; import org.robolectric.shadows.ShadowDialog; import org.robolectric.util.FragmentTestUtil; import java.util.ArrayList; import java.util.List; @RunWith(RobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class) public class RestrictedAppDetailsTest { private static final String PACKAGE_NAME = "com.android.app"; Loading @@ -60,20 +69,21 @@ public class RestrictedAppDetailsTest { private static final int UID = UserHandle.getUid(USER_ID, 234); private static final String APP_NAME = "app"; @Mock private PackageManager mPackageManager; @Mock private ApplicationInfo mApplicationInfo; @Mock private IconDrawableFactory mIconDrawableFactory; @Mock(answer = Answers.RETURNS_DEEP_STUBS) private PreferenceManager mPreferenceManager; @Mock private InstrumentedPreferenceFragment mFragment; private PreferenceManager mPreferenceManager; private RestrictedAppDetails mRestrictedAppDetails; private Context mContext; private AppInfo mAppInfo; private Intent mIntent; private CheckBoxPreference mCheckBoxPreference; @Before public void setUp() { Loading @@ -86,8 +96,9 @@ public class RestrictedAppDetailsTest { .setUid(UID) .build(); mPreferenceManager = new PreferenceManager(mContext); doReturn(mPreferenceManager).when(mRestrictedAppDetails).getPreferenceManager(); doReturn(mContext).when(mPreferenceManager).getContext(); doReturn(mContext).when(mFragment).getContext(); mRestrictedAppDetails.mPackageManager = mPackageManager; mRestrictedAppDetails.mIconDrawableFactory = mIconDrawableFactory; Loading @@ -97,10 +108,13 @@ public class RestrictedAppDetailsTest { mRestrictedAppDetails.mBatteryUtils = spy(new BatteryUtils(mContext)); doReturn(mPreferenceManager).when( mRestrictedAppDetails.mRestrictedAppListGroup).getPreferenceManager(); mCheckBoxPreference = new CheckBoxPreference(mContext); mCheckBoxPreference.setKey(mRestrictedAppDetails.getKeyFromAppInfo(mAppInfo)); } @Test public void testRefreshUi_displayPreference() throws Exception { public void refreshUi_displayPreference() throws Exception { doReturn(mApplicationInfo).when(mPackageManager) .getApplicationInfoAsUser(PACKAGE_NAME, 0, USER_ID); doReturn(APP_NAME).when(mPackageManager).getApplicationLabel(mApplicationInfo); Loading @@ -117,7 +131,7 @@ public class RestrictedAppDetailsTest { } @Test public void testStartRestrictedAppDetails_startWithCorrectData() { public void startRestrictedAppDetails_startWithCorrectData() { final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); doAnswer(invocation -> { // Get the intent in which it has the app info bundle Loading @@ -135,4 +149,50 @@ public class RestrictedAppDetailsTest { RestrictedAppDetails.EXTRA_APP_INFO_LIST); assertThat(appInfos).containsExactly(mAppInfo); } @Test public void createDialogFragment_toRestrict_createRestrictDialog() { final BatteryTipDialogFragment dialogFragment = mRestrictedAppDetails.createDialogFragment( mAppInfo, true); FragmentTestUtil.startFragment(dialogFragment); final AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog(); ShadowAlertDialog shadowDialog = shadowOf(dialog); assertThat(shadowDialog.getTitle()).isEqualTo("Restrict app?"); } @Test public void createDialogFragment_toUnrestrict_createUnrestrictDialog() { final BatteryTipDialogFragment dialogFragment = mRestrictedAppDetails.createDialogFragment( mAppInfo, false); FragmentTestUtil.startFragment(dialogFragment); final AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog(); ShadowAlertDialog shadowDialog = shadowOf(dialog); assertThat(shadowDialog.getTitle()).isEqualTo("Remove restriction?"); } @Test public void onBatteryTipHandled_restrict_setChecked() { final RestrictAppTip restrictAppTip = new RestrictAppTip(BatteryTip.StateType.NEW, mAppInfo); mRestrictedAppDetails.mRestrictedAppListGroup.addPreference(mCheckBoxPreference); mRestrictedAppDetails.onBatteryTipHandled(restrictAppTip); assertThat(mCheckBoxPreference.isChecked()).isTrue(); } @Test public void onBatteryTipHandled_unrestrict_setUnchecked() { final UnrestrictAppTip unrestrictAppTip = new UnrestrictAppTip(BatteryTip.StateType.NEW, mAppInfo); mRestrictedAppDetails.mRestrictedAppListGroup.addPreference(mCheckBoxPreference); mRestrictedAppDetails.onBatteryTipHandled(unrestrictAppTip); assertThat(mCheckBoxPreference.isChecked()).isFalse(); } }