Loading services/core/java/com/android/server/apphibernation/AppHibernationService.java +46 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.apphibernation; import static android.app.AppOpsManager.OP_NONE; import static android.content.Intent.ACTION_PACKAGE_ADDED; import static android.content.Intent.ACTION_PACKAGE_REMOVED; import static android.content.Intent.EXTRA_REMOVED_FOR_ALL_USERS; Loading @@ -25,8 +26,10 @@ import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION; import static com.android.server.apphibernation.AppHibernationConstants.KEY_APP_HIBERNATION_ENABLED; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityThread; import android.app.IActivityManager; Loading Loading @@ -366,6 +369,49 @@ public final class AppHibernationService extends SystemService { Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackage"); pkgState.hibernated = false; pkgState.lastUnhibernatedMs = System.currentTimeMillis(); // Deliver LOCKED_BOOT_COMPLETE AND BOOT_COMPLETE broadcast so app can re-register // their alarms/jobs/etc. try { Intent lockedBcIntent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED) .setPackage(packageName); final String[] requiredPermissions = {Manifest.permission.RECEIVE_BOOT_COMPLETED}; mIActivityManager.broadcastIntentWithFeature( null /* caller */, null /* callingFeatureId */, lockedBcIntent, null /* resolvedType */, null /* resultTo */, Activity.RESULT_OK, null /* resultData */, null /* resultExtras */, requiredPermissions, null /* excludedPermissions */, OP_NONE, null /* bOptions */, false /* serialized */, false /* sticky */, userId); Intent bcIntent = new Intent(Intent.ACTION_BOOT_COMPLETED).setPackage(packageName); mIActivityManager.broadcastIntentWithFeature( null /* caller */, null /* callingFeatureId */, bcIntent, null /* resolvedType */, null /* resultTo */, Activity.RESULT_OK, null /* resultData */, null /* resultExtras */, requiredPermissions, null /* excludedPermissions */, OP_NONE, null /* bOptions */, false /* serialized */, false /* sticky */, userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } Loading services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java +20 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import static org.mockito.ArgumentMatchers.intThat; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.app.IActivityManager; Loading Loading @@ -264,6 +265,25 @@ public final class AppHibernationServiceTest { assertFalse(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1)); } @Test public void testUnhibernatingPackageForUserSendsBootCompleteBroadcast() throws RemoteException { // GIVEN a hibernating package for a user mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true); // WHEN we unhibernate the package mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, false); // THEN we send the boot complete broadcasts ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); verify(mIActivityManager, times(2)).broadcastIntentWithFeature(any(), any(), intentArgumentCaptor.capture(), any(), any(), anyInt(), any(), any(), any(), any(), anyInt(), any(), anyBoolean(), anyBoolean(), eq(USER_ID_1)); List<Intent> capturedIntents = intentArgumentCaptor.getAllValues(); assertEquals(capturedIntents.get(0).getAction(), Intent.ACTION_LOCKED_BOOT_COMPLETED); assertEquals(capturedIntents.get(1).getAction(), Intent.ACTION_BOOT_COMPLETED); } /** * Add a mock user with one package. */ Loading Loading
services/core/java/com/android/server/apphibernation/AppHibernationService.java +46 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.apphibernation; import static android.app.AppOpsManager.OP_NONE; import static android.content.Intent.ACTION_PACKAGE_ADDED; import static android.content.Intent.ACTION_PACKAGE_REMOVED; import static android.content.Intent.EXTRA_REMOVED_FOR_ALL_USERS; Loading @@ -25,8 +26,10 @@ import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION; import static com.android.server.apphibernation.AppHibernationConstants.KEY_APP_HIBERNATION_ENABLED; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityThread; import android.app.IActivityManager; Loading Loading @@ -366,6 +369,49 @@ public final class AppHibernationService extends SystemService { Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackage"); pkgState.hibernated = false; pkgState.lastUnhibernatedMs = System.currentTimeMillis(); // Deliver LOCKED_BOOT_COMPLETE AND BOOT_COMPLETE broadcast so app can re-register // their alarms/jobs/etc. try { Intent lockedBcIntent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED) .setPackage(packageName); final String[] requiredPermissions = {Manifest.permission.RECEIVE_BOOT_COMPLETED}; mIActivityManager.broadcastIntentWithFeature( null /* caller */, null /* callingFeatureId */, lockedBcIntent, null /* resolvedType */, null /* resultTo */, Activity.RESULT_OK, null /* resultData */, null /* resultExtras */, requiredPermissions, null /* excludedPermissions */, OP_NONE, null /* bOptions */, false /* serialized */, false /* sticky */, userId); Intent bcIntent = new Intent(Intent.ACTION_BOOT_COMPLETED).setPackage(packageName); mIActivityManager.broadcastIntentWithFeature( null /* caller */, null /* callingFeatureId */, bcIntent, null /* resolvedType */, null /* resultTo */, Activity.RESULT_OK, null /* resultData */, null /* resultExtras */, requiredPermissions, null /* excludedPermissions */, OP_NONE, null /* bOptions */, false /* serialized */, false /* sticky */, userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } Loading
services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java +20 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import static org.mockito.ArgumentMatchers.intThat; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.app.IActivityManager; Loading Loading @@ -264,6 +265,25 @@ public final class AppHibernationServiceTest { assertFalse(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1)); } @Test public void testUnhibernatingPackageForUserSendsBootCompleteBroadcast() throws RemoteException { // GIVEN a hibernating package for a user mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true); // WHEN we unhibernate the package mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, false); // THEN we send the boot complete broadcasts ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); verify(mIActivityManager, times(2)).broadcastIntentWithFeature(any(), any(), intentArgumentCaptor.capture(), any(), any(), anyInt(), any(), any(), any(), any(), anyInt(), any(), anyBoolean(), anyBoolean(), eq(USER_ID_1)); List<Intent> capturedIntents = intentArgumentCaptor.getAllValues(); assertEquals(capturedIntents.get(0).getAction(), Intent.ACTION_LOCKED_BOOT_COMPLETED); assertEquals(capturedIntents.get(1).getAction(), Intent.ACTION_BOOT_COMPLETED); } /** * Add a mock user with one package. */ Loading