Merge "Hook up hibernation eligibility to exemption toggle"
diff --git a/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceController.java b/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceController.java
index d922867..f0b3329 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_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.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 @@
     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 @@
             String preferenceKey) {
         super(context, preferenceKey);
         mAppOpsManager = context.getSystemService(AppOpsManager.class);
+        mPermissionControllerManager = context.getSystemService(PermissionControllerManager.class);
     }
 
     @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
@@ -109,10 +116,27 @@
         }
     }
 
+    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 567594c..825a9b6 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.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.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 @@
 
     private HibernationSwitchPreferenceController mController;
     private Context mContext;
+    private String mOriginalPreSFlagValue;
 
     @Before
     public void setUp() throws PackageManager.NameNotFoundException {
@@ -89,6 +93,16 @@
                 "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 @@
     }
 
     @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 @@
                 .thenReturn(MODE_DEFAULT);
         mController.setPackage(EXEMPTED_PACKAGE_NAME);
 
-        mController.updateState(mPreference);
-
-        verify(mPreference).setChecked(true);
+        assertFalse(mController.isPackageHibernationExemptByUser());
     }
 }