From 143cc954f3877deef665677148e3d032a531b9c6 Mon Sep 17 00:00:00 2001 From: Kevin Han Date: Fri, 7 Jan 2022 18:42:08 -0800 Subject: [PATCH] Hook up hibernation eligibility to exemption toggle Use hibernation eligibility API to determine whether toggle should be enabled or disabled for an app. For apps that are already exempt from hibernation by the system, the toggle is disabled and unchecked. Bug: 200087723 Test: manual Test: atest AppHibernationIntegrationTest Change-Id: I36a1eafc2bb90a92bcbdc4bf32041426d6377fd4 --- ...HibernationSwitchPreferenceController.java | 26 ++++++++++++- ...rnationSwitchPreferenceControllerTest.java | 38 +++++++++++-------- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceController.java b/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceController.java index d9228673552..f0b332904de 100644 --- a/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceController.java @@ -20,6 +20,8 @@ import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.MODE_DEFAULT; import static android.app.AppOpsManager.MODE_IGNORED; import static android.app.AppOpsManager.OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED; +import static android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM; +import static android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_UNKNOWN; import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION; import static com.android.settings.Utils.PROPERTY_APP_HIBERNATION_ENABLED; @@ -29,6 +31,7 @@ import android.app.AppOpsManager; import android.apphibernation.AppHibernationManager; import android.content.Context; import android.content.pm.PackageManager; +import android.permission.PermissionControllerManager; import android.provider.DeviceConfig; import android.text.TextUtils; import android.util.Slog; @@ -51,7 +54,10 @@ public final class HibernationSwitchPreferenceController extends AppInfoPreferen private static final String TAG = "HibernationSwitchPrefController"; private String mPackageName; private final AppOpsManager mAppOpsManager; + private final PermissionControllerManager mPermissionControllerManager; private int mPackageUid; + private boolean mHibernationEligibilityLoaded; + private int mHibernationEligibility = HIBERNATION_ELIGIBILITY_UNKNOWN; @VisibleForTesting boolean mIsPackageSet; private boolean mIsPackageExemptByDefault; @@ -60,6 +66,7 @@ public final class HibernationSwitchPreferenceController extends AppInfoPreferen String preferenceKey) { super(context, preferenceKey); mAppOpsManager = context.getSystemService(AppOpsManager.class); + mPermissionControllerManager = context.getSystemService(PermissionControllerManager.class); } @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) @@ -109,10 +116,27 @@ public final class HibernationSwitchPreferenceController extends AppInfoPreferen } } + private boolean isAppEligibleForHibernation() { + return mHibernationEligibilityLoaded + && mHibernationEligibility != HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM + && mHibernationEligibility != HIBERNATION_ELIGIBILITY_UNKNOWN; + } + @Override public void updateState(Preference preference) { super.updateState(preference); - ((SwitchPreference) preference).setChecked(!isPackageHibernationExemptByUser()); + ((SwitchPreference) preference).setChecked(isAppEligibleForHibernation() + && !isPackageHibernationExemptByUser()); + preference.setEnabled(isAppEligibleForHibernation()); + if (!mHibernationEligibilityLoaded) { + mPermissionControllerManager.getHibernationEligibility(mPackageName, + mContext.getMainExecutor(), + eligibility -> { + mHibernationEligibility = eligibility; + mHibernationEligibilityLoaded = true; + updateState(preference); + }); + } } @VisibleForTesting diff --git a/tests/unit/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceControllerTest.java index 567594c8eb2..825a9b6bbe1 100644 --- a/tests/unit/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceControllerTest.java @@ -27,6 +27,8 @@ import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.spy; @@ -43,6 +45,7 @@ import androidx.preference.SwitchPreference; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -68,6 +71,7 @@ public class HibernationSwitchPreferenceControllerTest { private HibernationSwitchPreferenceController mController; private Context mContext; + private String mOriginalPreSFlagValue; @Before public void setUp() throws PackageManager.NameNotFoundException { @@ -89,6 +93,16 @@ public class HibernationSwitchPreferenceControllerTest { "true", true /* makeDefault */); mController = new HibernationSwitchPreferenceController(mContext, KEY); when(mPreference.getKey()).thenReturn(mController.getPreferenceKey()); + + mOriginalPreSFlagValue = DeviceConfig.getProperty(NAMESPACE_APP_HIBERNATION, + PROPERTY_HIBERNATION_TARGETS_PRE_S_APPS); + } + + @After + public void cleanUp() { + // Restore original device config values. + DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_HIBERNATION_TARGETS_PRE_S_APPS, + mOriginalPreSFlagValue, true /* makeDefault */); } @Test @@ -124,43 +138,37 @@ public class HibernationSwitchPreferenceControllerTest { } @Test - public void updateState_exemptedByDefaultPackage_shouldNotCheck() { + public void isPackageHibernationExemptByUser_preSAppShouldBeExemptByDefault() { when(mAppOpsManager.unsafeCheckOpNoThrow( eq(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED), anyInt(), eq(EXEMPTED_PACKAGE_NAME))) .thenReturn(MODE_DEFAULT); mController.setPackage(EXEMPTED_PACKAGE_NAME); - mController.updateState(mPreference); - - verify(mPreference).setChecked(false); + assertTrue(mController.isPackageHibernationExemptByUser()); } @Test - public void updateState_exemptedPackageOverrideByUser_shouldCheck() { + public void isPackageHibernationExemptByUser_preSAppShouldNotBeExemptWithUserSetting() { when(mAppOpsManager.unsafeCheckOpNoThrow( eq(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED), anyInt(), eq(EXEMPTED_PACKAGE_NAME))) .thenReturn(MODE_ALLOWED); mController.setPackage(EXEMPTED_PACKAGE_NAME); - mController.updateState(mPreference); - - verify(mPreference).setChecked(true); + assertFalse(mController.isPackageHibernationExemptByUser()); } @Test - public void updateState_unexemptedPackageOverrideByUser_shouldNotCheck() { + public void isPackageHibernationExemptByUser_SAppShouldBeExemptWithUserSetting() { when(mAppOpsManager.unsafeCheckOpNoThrow( eq(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED), anyInt(), eq(UNEXEMPTED_PACKAGE_NAME))) .thenReturn(MODE_IGNORED); mController.setPackage(UNEXEMPTED_PACKAGE_NAME); - mController.updateState(mPreference); - - verify(mPreference).setChecked(false); + assertTrue(mController.isPackageHibernationExemptByUser()); } @Test - public void updateState_exemptedByDefaultPackageOverriddenByPreSFlag_shouldCheck() { + public void isPackageHibernationExemptByUser_preSAppShouldNotBeExemptByDefaultWithPreSFlag() { DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_HIBERNATION_TARGETS_PRE_S_APPS, "true", true /* makeDefault */); when(mAppOpsManager.unsafeCheckOpNoThrow( @@ -168,8 +176,6 @@ public class HibernationSwitchPreferenceControllerTest { .thenReturn(MODE_DEFAULT); mController.setPackage(EXEMPTED_PACKAGE_NAME); - mController.updateState(mPreference); - - verify(mPreference).setChecked(true); + assertFalse(mController.isPackageHibernationExemptByUser()); } }