Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 24d67e9a authored by Kevin Han's avatar Kevin Han Committed by Android (Google) Code Review
Browse files

Merge "Hook up hibernation eligibility to exemption toggle"

parents fd3c59ae 143cc954
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -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
+22 −16
Original line number Diff line number Diff line
@@ -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());
    }
}