Merge "Exit hibernation when usage is detected" into sc-dev
This commit is contained in:
@@ -33,6 +33,9 @@ import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityThread;
|
||||
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.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@@ -148,8 +151,8 @@ public final class AppHibernationService extends SystemService {
|
||||
intentFilter.addAction(ACTION_PACKAGE_REMOVED);
|
||||
intentFilter.addDataScheme("package");
|
||||
userAllContext.registerReceiver(mBroadcastReceiver, intentFilter);
|
||||
|
||||
LocalServices.addService(AppHibernationManagerInternal.class, mLocalService);
|
||||
mInjector.getUsageStatsManagerInternal().registerListener(mUsageEventListener);
|
||||
}
|
||||
|
||||
@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.
|
||||
*
|
||||
@@ -817,6 +834,8 @@ public final class AppHibernationService extends SystemService {
|
||||
|
||||
Executor getBackgroundExecutor();
|
||||
|
||||
UsageStatsManagerInternal getUsageStatsManagerInternal();
|
||||
|
||||
HibernationStateDiskStore<GlobalLevelState> getGlobalLevelDiskStore();
|
||||
|
||||
HibernationStateDiskStore<UserLevelState> getUserLevelDiskStore(int userId);
|
||||
@@ -866,6 +885,11 @@ public final class AppHibernationService extends SystemService {
|
||||
return mScheduledExecutorService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UsageStatsManagerInternal getUsageStatsManagerInternal() {
|
||||
return LocalServices.getService(UsageStatsManagerInternal.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HibernationStateDiskStore<GlobalLevelState> getGlobalLevelDiskStore() {
|
||||
File dir = new File(Environment.getDataSystemDirectory(), HIBERNATION_DIR_NAME);
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
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 org.junit.Assert.assertEquals;
|
||||
@@ -34,6 +37,9 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
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.Context;
|
||||
import android.content.Intent;
|
||||
@@ -81,6 +87,8 @@ public final class AppHibernationServiceTest {
|
||||
|
||||
private AppHibernationService mAppHibernationService;
|
||||
private BroadcastReceiver mBroadcastReceiver;
|
||||
private UsageEventListener mUsageEventListener;
|
||||
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
@@ -93,8 +101,14 @@ public final class AppHibernationServiceTest {
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private HibernationStateDiskStore<UserLevelState> mUserLevelDiskStore;
|
||||
@Mock
|
||||
private UsageStatsManagerInternal mUsageStatsManagerInternal;
|
||||
@Mock
|
||||
private HibernationStateDiskStore<UserLevelState> mHibernationStateDiskStore;
|
||||
@Captor
|
||||
private ArgumentCaptor<BroadcastReceiver> mReceiverCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<UsageEventListener> mUsageEventListenerCaptor;
|
||||
|
||||
@Before
|
||||
public void setUp() throws RemoteException {
|
||||
@@ -108,6 +122,8 @@ public final class AppHibernationServiceTest {
|
||||
|
||||
verify(mContext).registerReceiver(mReceiverCaptor.capture(), any());
|
||||
mBroadcastReceiver = mReceiverCaptor.getValue();
|
||||
verify(mUsageStatsManagerInternal).registerListener(mUsageEventListenerCaptor.capture());
|
||||
mUsageEventListener = mUsageEventListenerCaptor.getValue();
|
||||
|
||||
doReturn(mUserInfos).when(mUserManager).getUsers();
|
||||
|
||||
@@ -284,6 +300,89 @@ public final class AppHibernationServiceTest {
|
||||
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.
|
||||
*/
|
||||
@@ -359,6 +458,11 @@ public final class AppHibernationServiceTest {
|
||||
return mUserManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UsageStatsManagerInternal getUsageStatsManagerInternal() {
|
||||
return mUsageStatsManagerInternal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Executor getBackgroundExecutor() {
|
||||
// Just execute immediately in tests.
|
||||
|
||||
Reference in New Issue
Block a user