Prevent UI jank
Move hide preference logic to getAvailabilityStatus, it can remove the preference before onresume. Fixes: 140366463 Test: manual, robolectric Change-Id: Ie11b5357b1e9340b30b8f19eac60c479cdb7687e
This commit is contained in:
@@ -49,6 +49,7 @@ public class RestrictAppPreferenceController extends BasePreferenceController {
|
|||||||
super(context, KEY_RESTRICT_APP);
|
super(context, KEY_RESTRICT_APP);
|
||||||
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
|
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
|
||||||
mUserManager = context.getSystemService(UserManager.class);
|
mUserManager = context.getSystemService(UserManager.class);
|
||||||
|
mAppInfos = BatteryTipUtils.getRestrictedAppsList(mAppOpsManager, mUserManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RestrictAppPreferenceController(InstrumentedPreferenceFragment preferenceFragment) {
|
public RestrictAppPreferenceController(InstrumentedPreferenceFragment preferenceFragment) {
|
||||||
@@ -58,21 +59,14 @@ public class RestrictAppPreferenceController extends BasePreferenceController {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAvailabilityStatus() {
|
public int getAvailabilityStatus() {
|
||||||
return AVAILABLE;
|
return mAppInfos.size() > 0 ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateState(Preference preference) {
|
public CharSequence getSummary() {
|
||||||
super.updateState(preference);
|
|
||||||
|
|
||||||
mAppInfos = BatteryTipUtils.getRestrictedAppsList(mAppOpsManager, mUserManager);
|
|
||||||
|
|
||||||
final int num = mAppInfos.size();
|
final int num = mAppInfos.size();
|
||||||
// Don't show it if no app been restricted
|
return mContext.getResources().getQuantityString(R.plurals.restricted_app_summary, num,
|
||||||
preference.setVisible(num > 0);
|
num);
|
||||||
preference.setSummary(
|
|
||||||
mContext.getResources().getQuantityString(R.plurals.restricted_app_summary, num,
|
|
||||||
num));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -68,7 +68,6 @@ public class SmartBatterySettings extends DashboardFragment {
|
|||||||
Context context, SettingsActivity settingsActivity,
|
Context context, SettingsActivity settingsActivity,
|
||||||
InstrumentedPreferenceFragment fragment) {
|
InstrumentedPreferenceFragment fragment) {
|
||||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||||
controllers.add(new SmartBatteryPreferenceController(context));
|
|
||||||
if (settingsActivity != null && fragment != null) {
|
if (settingsActivity != null && fragment != null) {
|
||||||
controllers.add(
|
controllers.add(
|
||||||
new RestrictAppPreferenceController(fragment));
|
new RestrictAppPreferenceController(fragment));
|
||||||
|
@@ -23,8 +23,10 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
@@ -34,6 +36,8 @@ import android.os.UserHandle;
|
|||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.core.InstrumentedPreferenceFragment;
|
import com.android.settings.core.InstrumentedPreferenceFragment;
|
||||||
@@ -46,10 +50,10 @@ import org.mockito.ArgumentCaptor;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.robolectric.Robolectric;
|
import org.robolectric.Robolectric;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
public class RestrictAppPreferenceControllerTest {
|
public class RestrictAppPreferenceControllerTest {
|
||||||
@@ -70,25 +74,23 @@ public class RestrictAppPreferenceControllerTest {
|
|||||||
private AppOpsManager.PackageOps mAllowedPackageOps;
|
private AppOpsManager.PackageOps mAllowedPackageOps;
|
||||||
private AppOpsManager.PackageOps mOtherUserPackageOps;
|
private AppOpsManager.PackageOps mOtherUserPackageOps;
|
||||||
private List<AppOpsManager.PackageOps> mPackageOpsList;
|
private List<AppOpsManager.PackageOps> mPackageOpsList;
|
||||||
private RestrictAppPreferenceController mRestrictAppPreferenceController;
|
|
||||||
private Preference mPreference;
|
private Preference mPreference;
|
||||||
|
private PreferenceScreen mPreferenceScreen;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
final AppOpsManager.OpEntry allowOpEntry = new AppOpsManager.OpEntry(
|
final List<AppOpsManager.OpEntry> allowOps = new ArrayList<>();
|
||||||
|
allowOps.add(new AppOpsManager.OpEntry(
|
||||||
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, false, AppOpsManager.MODE_ALLOWED,
|
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, false, AppOpsManager.MODE_ALLOWED,
|
||||||
null /*accessTimes*/, null /*rejectTimes*/, null /*durations*/,
|
null /*accessTimes*/, null /*rejectTimes*/, null /*durations*/,
|
||||||
null /* proxyUids */, null /* proxyPackages */);
|
null /* proxyUids */, null /* proxyPackages */));
|
||||||
final List<AppOpsManager.OpEntry> allowOps = new ArrayList<>();
|
final List<AppOpsManager.OpEntry> restrictedOps = new ArrayList<>();
|
||||||
allowOps.add(allowOpEntry);
|
restrictedOps.add(new AppOpsManager.OpEntry(
|
||||||
final AppOpsManager.OpEntry restrictedOpEntry = new AppOpsManager.OpEntry(
|
|
||||||
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, false, AppOpsManager.MODE_IGNORED,
|
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, false, AppOpsManager.MODE_IGNORED,
|
||||||
null /*accessTimes*/, null /*rejectTimes*/, null /*durations*/,
|
null /*accessTimes*/, null /*rejectTimes*/, null /*durations*/,
|
||||||
null /* proxyUids */, null /* proxyPackages */);
|
null /* proxyUids */, null /* proxyPackages */));
|
||||||
final List<AppOpsManager.OpEntry> restrictedOps = new ArrayList<>();
|
|
||||||
restrictedOps.add(restrictedOpEntry);
|
|
||||||
mAllowedPackageOps = new AppOpsManager.PackageOps(
|
mAllowedPackageOps = new AppOpsManager.PackageOps(
|
||||||
ALLOWED_PACKAGE_NAME, ALLOWED_UID, allowOps);
|
ALLOWED_PACKAGE_NAME, ALLOWED_UID, allowOps);
|
||||||
mRestrictedPackageOps = new AppOpsManager.PackageOps(
|
mRestrictedPackageOps = new AppOpsManager.PackageOps(
|
||||||
@@ -100,11 +102,15 @@ public class RestrictAppPreferenceControllerTest {
|
|||||||
doReturn(mAppOpsManager).when(mContext).getSystemService(Context.APP_OPS_SERVICE);
|
doReturn(mAppOpsManager).when(mContext).getSystemService(Context.APP_OPS_SERVICE);
|
||||||
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
|
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
|
||||||
doReturn(mContext).when(mFragment).getContext();
|
doReturn(mContext).when(mFragment).getContext();
|
||||||
mRestrictAppPreferenceController =
|
|
||||||
new RestrictAppPreferenceController(mFragment);
|
|
||||||
mPackageOpsList = new ArrayList<>();
|
mPackageOpsList = new ArrayList<>();
|
||||||
mPreference = new Preference(mContext);
|
mPreference = new Preference(mContext);
|
||||||
mPreference.setKey(mRestrictAppPreferenceController.getPreferenceKey());
|
mPreference.setKey(RestrictAppPreferenceController.KEY_RESTRICT_APP);
|
||||||
|
mPreferenceScreen = spy(new PreferenceScreen(mContext, null));
|
||||||
|
when(mPreferenceScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
|
||||||
|
when(mPreferenceScreen.getContext()).thenReturn(mContext);
|
||||||
|
when(mPreferenceScreen.findPreference(
|
||||||
|
RestrictAppPreferenceController.KEY_RESTRICT_APP)).thenReturn(mPreference);
|
||||||
|
|
||||||
final List<UserHandle> userHandles = new ArrayList<>();
|
final List<UserHandle> userHandles = new ArrayList<>();
|
||||||
userHandles.add(new UserHandle(0));
|
userHandles.add(new UserHandle(0));
|
||||||
@@ -112,40 +118,49 @@ public class RestrictAppPreferenceControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateState_oneApp_showCorrectSummary() {
|
public void updateState_oneApp_showCorrectSummary() {
|
||||||
mPackageOpsList.add(mRestrictedPackageOps);
|
mPackageOpsList.add(mRestrictedPackageOps);
|
||||||
doReturn(mPackageOpsList).when(mAppOpsManager).getPackagesForOps(any(int[].class));
|
doReturn(mPackageOpsList).when(mAppOpsManager).getPackagesForOps(any(int[].class));
|
||||||
|
|
||||||
mRestrictAppPreferenceController.updateState(mPreference);
|
final RestrictAppPreferenceController controller = new RestrictAppPreferenceController(
|
||||||
|
mFragment);
|
||||||
|
controller.displayPreference(mPreferenceScreen);
|
||||||
|
controller.updateState(mPreference);
|
||||||
|
|
||||||
assertThat(mPreference.getSummary()).isEqualTo("Limiting battery usage for 1 app");
|
assertThat(mPreference.getSummary()).isEqualTo("Limiting battery usage for 1 app");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateState_twoRestrictedAppsForPrimaryUser_visibleAndShowCorrectSummary() {
|
public void updateState_twoRestrictedAppsForPrimaryUser_visibleAndShowCorrectSummary() {
|
||||||
mPackageOpsList.add(mRestrictedPackageOps);
|
mPackageOpsList.add(mRestrictedPackageOps);
|
||||||
mPackageOpsList.add(mRestrictedPackageOps);
|
mPackageOpsList.add(mRestrictedPackageOps);
|
||||||
mPackageOpsList.add(mAllowedPackageOps);
|
mPackageOpsList.add(mAllowedPackageOps);
|
||||||
mPackageOpsList.add(mOtherUserPackageOps);
|
mPackageOpsList.add(mOtherUserPackageOps);
|
||||||
doReturn(mPackageOpsList).when(mAppOpsManager).getPackagesForOps(any(int[].class));
|
doReturn(mPackageOpsList).when(mAppOpsManager).getPackagesForOps(any(int[].class));
|
||||||
|
|
||||||
mRestrictAppPreferenceController.updateState(mPreference);
|
final RestrictAppPreferenceController controller = new RestrictAppPreferenceController(
|
||||||
|
mFragment);
|
||||||
|
controller.displayPreference(mPreferenceScreen);
|
||||||
|
controller.updateState(mPreference);
|
||||||
|
|
||||||
assertThat(mPreference.getSummary()).isEqualTo("Limiting battery usage for 2 apps");
|
assertThat(mPreference.getSummary()).isEqualTo("Limiting battery usage for 2 apps");
|
||||||
assertThat(mPreference.isVisible()).isTrue();
|
assertThat(mPreference.isVisible()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateState_oneRestrictedAppForTwoUsers_showSummaryAndContainCorrectApp() {
|
public void updateState_oneRestrictedAppForTwoUsers_showSummaryAndContainCorrectApp() {
|
||||||
// Two packageOps share same package name but different uid.
|
// Two packageOps share same package name but different uid.
|
||||||
mPackageOpsList.add(mRestrictedPackageOps);
|
mPackageOpsList.add(mRestrictedPackageOps);
|
||||||
mPackageOpsList.add(mOtherUserPackageOps);
|
mPackageOpsList.add(mOtherUserPackageOps);
|
||||||
doReturn(mPackageOpsList).when(mAppOpsManager).getPackagesForOps(any(int[].class));
|
doReturn(mPackageOpsList).when(mAppOpsManager).getPackagesForOps(any(int[].class));
|
||||||
|
|
||||||
mRestrictAppPreferenceController.updateState(mPreference);
|
final RestrictAppPreferenceController controller = new RestrictAppPreferenceController(
|
||||||
|
mFragment);
|
||||||
|
controller.displayPreference(mPreferenceScreen);
|
||||||
|
controller.updateState(mPreference);
|
||||||
|
|
||||||
assertThat(mPreference.getSummary()).isEqualTo("Limiting battery usage for 1 app");
|
assertThat(mPreference.getSummary()).isEqualTo("Limiting battery usage for 1 app");
|
||||||
assertThat(mRestrictAppPreferenceController.mAppInfos).containsExactly(
|
assertThat(controller.mAppInfos).containsExactly(
|
||||||
new AppInfo.Builder()
|
new AppInfo.Builder()
|
||||||
.setUid(RESTRICTED_UID)
|
.setUid(RESTRICTED_UID)
|
||||||
.setPackageName(RESTRICTED_PACKAGE_NAME)
|
.setPackageName(RESTRICTED_PACKAGE_NAME)
|
||||||
@@ -153,20 +168,25 @@ public class RestrictAppPreferenceControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateState_zeroRestrictApp_inVisible() {
|
public void updateState_zeroRestrictApp_inVisible() {
|
||||||
mPackageOpsList.add(mAllowedPackageOps);
|
mPackageOpsList.add(mAllowedPackageOps);
|
||||||
doReturn(mPackageOpsList).when(mAppOpsManager).getPackagesForOps(any(int[].class));
|
doReturn(mPackageOpsList).when(mAppOpsManager).getPackagesForOps(any(int[].class));
|
||||||
|
|
||||||
mRestrictAppPreferenceController.updateState(mPreference);
|
final RestrictAppPreferenceController controller = new RestrictAppPreferenceController(
|
||||||
|
mFragment);
|
||||||
|
controller.displayPreference(mPreferenceScreen);
|
||||||
|
controller.updateState(mPreference);
|
||||||
|
|
||||||
assertThat(mPreference.isVisible()).isFalse();
|
assertThat(mPreference.isVisible()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHandlePreferenceTreeClick_startFragment() {
|
public void handlePreferenceTreeClick_startFragment() {
|
||||||
final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
|
final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
|
||||||
|
|
||||||
mRestrictAppPreferenceController.handlePreferenceTreeClick(mPreference);
|
final RestrictAppPreferenceController controller = new RestrictAppPreferenceController(
|
||||||
|
mFragment);
|
||||||
|
controller.handlePreferenceTreeClick(mPreference);
|
||||||
|
|
||||||
verify(mContext).startActivity(intent.capture());
|
verify(mContext).startActivity(intent.capture());
|
||||||
assertThat(intent.getValue().getStringExtra(EXTRA_SHOW_FRAGMENT))
|
assertThat(intent.getValue().getStringExtra(EXTRA_SHOW_FRAGMENT))
|
||||||
|
Reference in New Issue
Block a user