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

Commit 28eab4f2 authored by Kevin Han's avatar Kevin Han Committed by Automerger Merge Worker
Browse files

Merge "Exit hibernation when usage is detected" into sc-dev am: f3040a45

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14315868

Change-Id: I0d3018cfe9f4f9ceebffde56b5c784876acfee02
parents 0be69088 f3040a45
Loading
Loading
Loading
Loading
+25 −1
Original line number Original line Diff line number Diff line
@@ -33,6 +33,9 @@ import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.ActivityThread;
import android.app.IActivityManager;
import android.app.IActivityManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal.UsageEventListener;
import android.apphibernation.IAppHibernationService;
import android.apphibernation.IAppHibernationService;
import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Context;
@@ -148,8 +151,8 @@ public final class AppHibernationService extends SystemService {
        intentFilter.addAction(ACTION_PACKAGE_REMOVED);
        intentFilter.addAction(ACTION_PACKAGE_REMOVED);
        intentFilter.addDataScheme("package");
        intentFilter.addDataScheme("package");
        userAllContext.registerReceiver(mBroadcastReceiver, intentFilter);
        userAllContext.registerReceiver(mBroadcastReceiver, intentFilter);

        LocalServices.addService(AppHibernationManagerInternal.class, mLocalService);
        LocalServices.addService(AppHibernationManagerInternal.class, mLocalService);
        mInjector.getUsageStatsManagerInternal().registerListener(mUsageEventListener);
    }
    }


    @Override
    @Override
@@ -785,6 +788,20 @@ public final class AppHibernationService extends SystemService {
        }
        }
    };
    };


    private final UsageEventListener mUsageEventListener = (userId, event) -> {
        if (!isAppHibernationEnabled()) {
            return;
        }
        final int eventType = event.mEventType;
        if (eventType == UsageEvents.Event.USER_INTERACTION
                || eventType == UsageEvents.Event.ACTIVITY_RESUMED
                || eventType == UsageEvents.Event.APP_COMPONENT_USED) {
            final String pkgName = event.mPackage;
            setHibernatingForUser(pkgName, userId, false);
            setHibernatingGlobally(pkgName, false);
        }
    };

    /**
    /**
     * Whether app hibernation is enabled on this device.
     * Whether app hibernation is enabled on this device.
     *
     *
@@ -817,6 +834,8 @@ public final class AppHibernationService extends SystemService {


        Executor getBackgroundExecutor();
        Executor getBackgroundExecutor();


        UsageStatsManagerInternal getUsageStatsManagerInternal();

        HibernationStateDiskStore<GlobalLevelState> getGlobalLevelDiskStore();
        HibernationStateDiskStore<GlobalLevelState> getGlobalLevelDiskStore();


        HibernationStateDiskStore<UserLevelState> getUserLevelDiskStore(int userId);
        HibernationStateDiskStore<UserLevelState> getUserLevelDiskStore(int userId);
@@ -866,6 +885,11 @@ public final class AppHibernationService extends SystemService {
            return mScheduledExecutorService;
            return mScheduledExecutorService;
        }
        }


        @Override
        public UsageStatsManagerInternal getUsageStatsManagerInternal() {
            return LocalServices.getService(UsageStatsManagerInternal.class);
        }

        @Override
        @Override
        public HibernationStateDiskStore<GlobalLevelState> getGlobalLevelDiskStore() {
        public HibernationStateDiskStore<GlobalLevelState> getGlobalLevelDiskStore() {
            File dir = new File(Environment.getDataSystemDirectory(), HIBERNATION_DIR_NAME);
            File dir = new File(Environment.getDataSystemDirectory(), HIBERNATION_DIR_NAME);
+104 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,9 @@


package com.android.server.apphibernation;
package com.android.server.apphibernation;


import static android.app.usage.UsageEvents.Event.ACTIVITY_RESUMED;
import static android.app.usage.UsageEvents.Event.APP_COMPONENT_USED;
import static android.app.usage.UsageEvents.Event.USER_INTERACTION;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.content.pm.PackageManager.MATCH_ANY_USER;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
@@ -34,6 +37,9 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verify;


import android.app.IActivityManager;
import android.app.IActivityManager;
import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal.UsageEventListener;
import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
@@ -81,6 +87,8 @@ public final class AppHibernationServiceTest {


    private AppHibernationService mAppHibernationService;
    private AppHibernationService mAppHibernationService;
    private BroadcastReceiver mBroadcastReceiver;
    private BroadcastReceiver mBroadcastReceiver;
    private UsageEventListener mUsageEventListener;

    @Mock
    @Mock
    private Context mContext;
    private Context mContext;
    @Mock
    @Mock
@@ -93,8 +101,14 @@ public final class AppHibernationServiceTest {
    private UserManager mUserManager;
    private UserManager mUserManager;
    @Mock
    @Mock
    private HibernationStateDiskStore<UserLevelState> mUserLevelDiskStore;
    private HibernationStateDiskStore<UserLevelState> mUserLevelDiskStore;
    @Mock
    private UsageStatsManagerInternal mUsageStatsManagerInternal;
    @Mock
    private HibernationStateDiskStore<UserLevelState> mHibernationStateDiskStore;
    @Captor
    @Captor
    private ArgumentCaptor<BroadcastReceiver> mReceiverCaptor;
    private ArgumentCaptor<BroadcastReceiver> mReceiverCaptor;
    @Captor
    private ArgumentCaptor<UsageEventListener> mUsageEventListenerCaptor;


    @Before
    @Before
    public void setUp() throws RemoteException {
    public void setUp() throws RemoteException {
@@ -108,6 +122,8 @@ public final class AppHibernationServiceTest {


        verify(mContext).registerReceiver(mReceiverCaptor.capture(), any());
        verify(mContext).registerReceiver(mReceiverCaptor.capture(), any());
        mBroadcastReceiver = mReceiverCaptor.getValue();
        mBroadcastReceiver = mReceiverCaptor.getValue();
        verify(mUsageStatsManagerInternal).registerListener(mUsageEventListenerCaptor.capture());
        mUsageEventListener = mUsageEventListenerCaptor.getValue();


        doReturn(mUserInfos).when(mUserManager).getUsers();
        doReturn(mUserInfos).when(mUserManager).getUsers();


@@ -284,6 +300,89 @@ public final class AppHibernationServiceTest {
        assertEquals(capturedIntents.get(1).getAction(), Intent.ACTION_BOOT_COMPLETED);
        assertEquals(capturedIntents.get(1).getAction(), Intent.ACTION_BOOT_COMPLETED);
    }
    }


    @Test
    public void testHibernatingPackageIsUnhibernatedForUserWhenUserInteracted() {
        // GIVEN a package that is currently hibernated for a user
        mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true);

        // WHEN the package is interacted with by user
        generateUsageEvent(USER_INTERACTION);

        // THEN the package is not hibernating anymore
        assertFalse(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1));
    }

    @Test
    public void testHibernatingPackageIsUnhibernatedForUserWhenActivityResumed() {
        // GIVEN a package that is currently hibernated for a user
        mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true);

        // WHEN the package has activity resumed
        generateUsageEvent(ACTIVITY_RESUMED);

        // THEN the package is not hibernating anymore
        assertFalse(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1));
    }

    @Test
    public void testHibernatingPackageIsUnhibernatedForUserWhenComponentUsed() {
        // GIVEN a package that is currently hibernated for a user
        mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true);

        // WHEN a package component is used
        generateUsageEvent(APP_COMPONENT_USED);

        // THEN the package is not hibernating anymore
        assertFalse(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1));
    }

    @Test
    public void testHibernatingPackageIsUnhibernatedGloballyWhenUserInteracted() {
        // GIVEN a package that is currently hibernated globally
        mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true);

        // WHEN the user interacts with the package
        generateUsageEvent(USER_INTERACTION);

        // THEN the package is not hibernating globally anymore
        assertFalse(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1));
    }

    @Test
    public void testHibernatingPackageIsUnhibernatedGloballyWhenActivityResumed() {
        // GIVEN a package that is currently hibernated globally
        mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true);

        // WHEN activity in package resumed
        generateUsageEvent(ACTIVITY_RESUMED);

        // THEN the package is not hibernating globally anymore
        assertFalse(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1));
    }

    @Test
    public void testHibernatingPackageIsUnhibernatedGloballyWhenComponentUsed() {
        // GIVEN a package that is currently hibernated globally
        mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true);

        // WHEN a package component is used
        generateUsageEvent(APP_COMPONENT_USED);

        // THEN the package is not hibernating globally anymore
        assertFalse(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1));
    }

    /**
     * Mock a usage event occurring.
     *
     * @param usageEventId id of a usage event
     */
    private void generateUsageEvent(int usageEventId) {
        Event event = new Event(usageEventId, 0 /* timestamp */);
        event.mPackage = PACKAGE_NAME_1;
        mUsageEventListener.onUsageEvent(USER_ID_1, event);
    }

    /**
    /**
     * Add a mock user with one package.
     * Add a mock user with one package.
     */
     */
@@ -359,6 +458,11 @@ public final class AppHibernationServiceTest {
            return mUserManager;
            return mUserManager;
        }
        }


        @Override
        public UsageStatsManagerInternal getUsageStatsManagerInternal() {
            return mUsageStatsManagerInternal;
        }

        @Override
        @Override
        public Executor getBackgroundExecutor() {
        public Executor getBackgroundExecutor() {
            // Just execute immediately in tests.
            // Just execute immediately in tests.