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

Commit 59aa4f9c authored by Zhen Zhang's avatar Zhen Zhang Committed by Android (Google) Code Review
Browse files

Merge "Update summary based on hibernated apps number" into sc-dev

parents 81a76170 1f99d6a4
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -107,6 +107,7 @@
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="android.permission.READ_DREAM_STATE" />
    <uses-permission android:name="android.permission.READ_DREAM_STATE" />
    <uses-permission android:name="android.permission.READ_DREAM_SUPPRESSION" />
    <uses-permission android:name="android.permission.READ_DREAM_SUPPRESSION" />
    <uses-permission android:name="android.permission.MANAGE_APP_HIBERNATION" />


    <application android:label="@string/settings_label"
    <application android:label="@string/settings_label"
            android:icon="@drawable/ic_launcher_settings"
            android:icon="@drawable/ic_launcher_settings"
+28 −4
Original line number Original line Diff line number Diff line
@@ -20,15 +20,19 @@ import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION;


import static com.android.settings.Utils.PROPERTY_APP_HIBERNATION_ENABLED;
import static com.android.settings.Utils.PROPERTY_APP_HIBERNATION_ENABLED;


import android.apphibernation.AppHibernationManager;
import android.content.Context;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig;


import com.android.settings.R;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.BasePreferenceController;


import java.util.List;

/**
/**
 * A preference controller handling the logic for updating summary of hibernated apps.
 * A preference controller handling the logic for updating summary of hibernated apps.
 * TODO(b/181172051): add intent to launch Auto Revoke UI in app_and_notification.xml
 */
 */
public final class HibernatedAppsPreferenceController extends BasePreferenceController {
public final class HibernatedAppsPreferenceController extends BasePreferenceController {
    private static final String TAG = "HibernatedAppsPrefController";
    private static final String TAG = "HibernatedAppsPrefController";
@@ -39,7 +43,8 @@ public final class HibernatedAppsPreferenceController extends BasePreferenceCont


    @Override
    @Override
    public int getAvailabilityStatus() {
    public int getAvailabilityStatus() {
        return isHibernationEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
        return isHibernationEnabled() && getNumHibernated() > 0
                ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
    }
    }


    @Override
    @Override
@@ -50,8 +55,27 @@ public final class HibernatedAppsPreferenceController extends BasePreferenceCont
    }
    }


    private int getNumHibernated() {
    private int getNumHibernated() {
        //TODO(b/181172051): hook into hibernation service to get the number of hibernated apps.
        final PackageManager pm = mContext.getPackageManager();
        return 0;
        final AppHibernationManager ahm = mContext.getSystemService(AppHibernationManager.class);
        final List<String> hibernatedPackages = ahm.getHibernatingPackagesForUser();
        int numHibernated = hibernatedPackages.size();

        // Also need to count packages that are auto revoked but not hibernated.
        final List<PackageInfo> packages = pm.getInstalledPackages(
                PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.GET_PERMISSIONS);
        for (PackageInfo pi : packages) {
            final String packageName = pi.packageName;
            if (!hibernatedPackages.contains(packageName) && pi.requestedPermissions != null) {
                for (String perm : pi.requestedPermissions) {
                    if ((pm.getPermissionFlags(perm, packageName, mContext.getUser())
                            & PackageManager.FLAG_PERMISSION_AUTO_REVOKED) != 0) {
                        numHibernated++;
                        break;
                    }
                }
            }
        }
        return numHibernated;
    }
    }


    private static boolean isHibernationEnabled() {
    private static boolean isHibernationEnabled() {
+3 −3
Original line number Original line Diff line number Diff line
@@ -80,7 +80,8 @@ public final class HibernationSwitchPreferenceController extends AppInfoPreferen


    /**
    /**
     * Set the package. And also retrieve details from package manager. Some packages may be
     * Set the package. And also retrieve details from package manager. Some packages may be
     * exempted from hibernation by default.
     * exempted from hibernation by default. This method should only be called to initialize the
     * controller.
     * @param packageName The name of the package whose hibernation state to be managed.
     * @param packageName The name of the package whose hibernation state to be managed.
     */
     */
    void setPackage(@NonNull String packageName) {
    void setPackage(@NonNull String packageName) {
@@ -93,8 +94,7 @@ public final class HibernationSwitchPreferenceController extends AppInfoPreferen
                        ? android.os.Build.VERSION_CODES.R
                        ? android.os.Build.VERSION_CODES.R
                        : android.os.Build.VERSION_CODES.Q;
                        : android.os.Build.VERSION_CODES.Q;
        try {
        try {
            mPackageUid = packageManager.getPackageUidAsUser(
            mPackageUid = packageManager.getPackageUid(packageName, /* flags */ 0);
                    packageName, mContext.getUserId());
            mIsPackageExemptByDefault = packageManager.getTargetSdkVersion(packageName)
            mIsPackageExemptByDefault = packageManager.getTargetSdkVersion(packageName)
                    <= maxTargetSdkVersionForExemptApps;
                    <= maxTargetSdkVersionForExemptApps;
            mIsPackageSet = true;
            mIsPackageSet = true;
+63 −3
Original line number Original line Diff line number Diff line
@@ -23,9 +23,18 @@ import static com.android.settings.core.BasePreferenceController.AVAILABLE;


import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertThat;


import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
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.when;


import android.apphibernation.AppHibernationManager;
import android.content.Context;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig;


import androidx.test.core.app.ApplicationProvider;
import androidx.test.core.app.ApplicationProvider;
@@ -34,23 +43,40 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Before;
import org.junit.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.Arrays;


/**
 * TODO(b/181172051): test getNumberHibernated() when the API implemented
 */
@RunWith(AndroidJUnit4.class)
@RunWith(AndroidJUnit4.class)
public class HibernatedAppsPreferenceControllerTest {
public class HibernatedAppsPreferenceControllerTest {


    public static final String HIBERNATED_PACKAGE_NAME = "hibernated_package";
    public static final String AUTO_REVOKED_PACKAGE_NAME = "auto_revoked_package";
    public static final String PERMISSION = "permission";
    @Mock
    PackageManager mPackageManager;
    @Mock
    AppHibernationManager mAppHibernationManager;
    private static final String KEY = "key";
    private static final String KEY = "key";
    private Context mContext;
    private Context mContext;
    private HibernatedAppsPreferenceController mController;
    private HibernatedAppsPreferenceController mController;
    private PackageInfo mHibernatedPackage;
    private PackageInfo mAutoRevokedPackage;


    @Before
    @Before
    public void setUp() {
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
        DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
                "true", false);
                "true", false);
        mContext = spy(ApplicationProvider.getApplicationContext());
        mContext = spy(ApplicationProvider.getApplicationContext());
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        when(mContext.getSystemService(AppHibernationManager.class))
                .thenReturn(mAppHibernationManager);
        mController = new HibernatedAppsPreferenceController(mContext, KEY);
        mController = new HibernatedAppsPreferenceController(mContext, KEY);
        mHibernatedPackage =
                getHibernatedPackage(mAppHibernationManager, mPackageManager, mContext);
        mAutoRevokedPackage = getAutoRevokedPackage(mPackageManager, mContext);
    }
    }


    @Test
    @Test
@@ -60,4 +86,38 @@ public class HibernatedAppsPreferenceControllerTest {


        assertThat((mController).getAvailabilityStatus()).isNotEqualTo(AVAILABLE);
        assertThat((mController).getAvailabilityStatus()).isNotEqualTo(AVAILABLE);
    }
    }

    @Test
    public void getSummary_shouldReturnCorrectly() {
        when(mPackageManager.getInstalledPackages(anyInt())).thenReturn(
                Arrays.asList(mHibernatedPackage, mAutoRevokedPackage, new PackageInfo()));
        when(mContext.getResources()).thenReturn(mock(Resources.class));
        final int totalHibernated = 2;

        mController.getSummary();
        verify(mContext.getResources()).getQuantityString(
                anyInt(), eq(totalHibernated), eq(totalHibernated));
    }

    private static PackageInfo getHibernatedPackage(
            AppHibernationManager apm, PackageManager pm, Context context) {
        final PackageInfo pi = new PackageInfo();
        pi.packageName = HIBERNATED_PACKAGE_NAME;
        pi.requestedPermissions = new String[] {PERMISSION};
        when(apm.getHibernatingPackagesForUser()).thenReturn(Arrays.asList(pi.packageName));
        when(pm.getPermissionFlags(
                pi.requestedPermissions[0], pi.packageName, context.getUser()))
                .thenReturn(PackageManager.FLAG_PERMISSION_AUTO_REVOKED);
        return pi;
    }

    private static PackageInfo getAutoRevokedPackage(PackageManager pm, Context context) {
        final PackageInfo pi = new PackageInfo();
        pi.packageName = AUTO_REVOKED_PACKAGE_NAME;
        pi.requestedPermissions = new String[] {PERMISSION};
        when(pm.getPermissionFlags(
                pi.requestedPermissions[0], pi.packageName, context.getUser()))
                .thenReturn(PackageManager.FLAG_PERMISSION_AUTO_REVOKED);
        return pi;
    }
}
}