Loading services/core/java/com/android/server/apphibernation/AppHibernationService.java +20 −38 Original line number Diff line number Diff line Loading @@ -18,8 +18,6 @@ package com.android.server.apphibernation; import static android.content.Intent.ACTION_PACKAGE_ADDED; import static android.content.Intent.ACTION_PACKAGE_REMOVED; import static android.content.Intent.ACTION_USER_ADDED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_REMOVED_FOR_ALL_USERS; import static android.content.Intent.EXTRA_REPLACING; import static android.content.pm.PackageManager.MATCH_ALL; Loading @@ -36,7 +34,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.UserInfo; import android.os.Binder; import android.os.RemoteException; import android.os.ResultReceiver; Loading @@ -48,6 +45,7 @@ import android.os.UserManager; import android.provider.DeviceConfig; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; Loading Loading @@ -107,11 +105,6 @@ public final class AppHibernationService extends SystemService { final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ACTION_USER_ADDED); intentFilter.addAction(ACTION_USER_REMOVED); userAllContext.registerReceiver(mBroadcastReceiver, intentFilter); intentFilter = new IntentFilter(); intentFilter.addAction(ACTION_PACKAGE_ADDED); intentFilter.addAction(ACTION_PACKAGE_REMOVED); intentFilter.addDataScheme("package"); Loading @@ -123,19 +116,6 @@ public final class AppHibernationService extends SystemService { publishBinderService(Context.APP_HIBERNATION_SERVICE, mServiceStub); } @Override public void onBootPhase(int phase) { if (phase == PHASE_BOOT_COMPLETED) { synchronized (mLock) { final List<UserInfo> users = mUserManager.getUsers(); // TODO: Pull from persistent disk storage. For now, just make from scratch. for (UserInfo user : users) { addUserPackageStatesL(user.id); } } } } /** * Whether a package is hibernating for a given user. * Loading @@ -145,11 +125,13 @@ public final class AppHibernationService extends SystemService { */ boolean isHibernatingForUser(String packageName, int userId) { userId = handleIncomingUser(userId, "isHibernating"); if (!mUserManager.isUserUnlockingOrUnlocked(userId)) { Slog.e(TAG, "Attempt to get hibernation state of stopped or nonexistent user " + userId); return false; } synchronized (mLock) { final Map<String, UserPackageState> packageStates = mUserStates.get(userId); if (packageStates == null) { throw new IllegalArgumentException("No user associated with user id " + userId); } final UserPackageState pkgState = packageStates.get(packageName); if (pkgState == null) { throw new IllegalArgumentException( Loading Loading @@ -181,10 +163,12 @@ public final class AppHibernationService extends SystemService { */ void setHibernatingForUser(String packageName, int userId, boolean isHibernating) { userId = handleIncomingUser(userId, "setHibernating"); synchronized (mLock) { if (!mUserStates.contains(userId)) { throw new IllegalArgumentException("No user associated with user id " + userId); if (!mUserManager.isUserUnlockingOrUnlocked(userId)) { Slog.w(TAG, "Attempt to set hibernation state for a stopped or nonexistent user " + userId); return; } synchronized (mLock) { Map<String, UserPackageState> packageStates = mUserStates.get(userId); UserPackageState pkgState = packageStates.get(packageName); if (pkgState == null) { Loading Loading @@ -310,15 +294,19 @@ public final class AppHibernationService extends SystemService { mUserStates.put(userId, packages); } private void onUserAdded(int userId) { @Override public void onUserUnlocking(@NonNull TargetUser user) { // TODO: Pull from persistent disk storage. For now, just make from scratch. synchronized (mLock) { addUserPackageStatesL(userId); addUserPackageStatesL(user.getUserIdentifier()); } } private void onUserRemoved(int userId) { @Override public void onUserStopping(@NonNull TargetUser user) { synchronized (mLock) { mUserStates.remove(userId); // TODO: Flush to disk when persistence is implemented mUserStates.remove(user.getUserIdentifier()); } } Loading Loading @@ -395,7 +383,7 @@ public final class AppHibernationService extends SystemService { } } // Broadcast receiver for user and package add/removal events // Broadcast receiver for package add/removal events private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Loading @@ -405,12 +393,6 @@ public final class AppHibernationService extends SystemService { } final String action = intent.getAction(); if (ACTION_USER_ADDED.equals(action)) { onUserAdded(userId); } if (ACTION_USER_REMOVED.equals(action)) { onUserRemoved(userId); } if (ACTION_PACKAGE_ADDED.equals(action) || ACTION_PACKAGE_REMOVED.equals(action)) { final String packageName = intent.getData().getSchemeSpecificPart(); if (intent.getBooleanExtra(EXTRA_REPLACING, false)) { Loading services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java +20 −27 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import static org.mockito.internal.verification.VerificationModeFactory.times; import android.app.IActivityManager; import android.content.BroadcastReceiver; Loading Loading @@ -87,7 +86,7 @@ public final class AppHibernationServiceTest { mAppHibernationService = new AppHibernationService(mContext, mIPackageManager, mIActivityManager, mUserManager); verify(mContext, times(2)).registerReceiver(mReceiverCaptor.capture(), any()); verify(mContext).registerReceiver(mReceiverCaptor.capture(), any()); mBroadcastReceiver = mReceiverCaptor.getValue(); doReturn(mUserInfos).when(mUserManager).getUsers(); Loading @@ -95,12 +94,13 @@ public final class AppHibernationServiceTest { doAnswer(returnsArgAt(2)).when(mIActivityManager).handleIncomingUser(anyInt(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any(), any()); addUser(USER_ID_1); mAppHibernationService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); UserInfo userInfo = addUser(USER_ID_1); mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(userInfo)); doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_1); } @Test public void testSetHibernatingForUser_packageIsHibernating() throws RemoteException { public void testSetHibernatingForUser_packageIsHibernating() { // WHEN we hibernate a package for a user mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true); Loading @@ -109,8 +109,7 @@ public final class AppHibernationServiceTest { } @Test public void testSetHibernatingForUser_newPackageAdded_packageIsHibernating() throws RemoteException { public void testSetHibernatingForUser_newPackageAdded_packageIsHibernating() { // WHEN a new package is added and it is hibernated Intent intent = new Intent(Intent.ACTION_PACKAGE_ADDED, Uri.fromParts(PACKAGE_SCHEME, PACKAGE_NAME_2, null /* fragment */)); Loading @@ -124,17 +123,12 @@ public final class AppHibernationServiceTest { } @Test public void testSetHibernatingForUser_newUserAdded_packageIsHibernating() public void testSetHibernatingForUser_newUserUnlocked_packageIsHibernating() throws RemoteException { // WHEN a new user is added and a package from the user is hibernated List<PackageInfo> userPackages = new ArrayList<>(); userPackages.add(makePackageInfo(PACKAGE_NAME_1)); doReturn(new ParceledListSlice<>(userPackages)).when(mIPackageManager) .getInstalledPackages(anyInt(), eq(USER_ID_2)); Intent intent = new Intent(Intent.ACTION_USER_ADDED); intent.putExtra(Intent.EXTRA_USER_HANDLE, USER_ID_2); mBroadcastReceiver.onReceive(mContext, intent); UserInfo user2 = addUser(USER_ID_2); mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(user2)); doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_2); mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_2, true); // THEN the new user's package is hibernated Loading @@ -142,8 +136,7 @@ public final class AppHibernationServiceTest { } @Test public void testIsHibernatingForUser_packageReplaced_stillReturnsHibernating() throws RemoteException { public void testIsHibernatingForUser_packageReplaced_stillReturnsHibernating() { // GIVEN a package is currently hibernated mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true); Loading @@ -159,7 +152,7 @@ public final class AppHibernationServiceTest { } @Test public void testSetHibernatingGlobally_packageIsHibernatingGlobally() throws RemoteException { public void testSetHibernatingGlobally_packageIsHibernatingGlobally() { // WHEN we hibernate a package mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true); Loading @@ -168,25 +161,25 @@ public final class AppHibernationServiceTest { } /** * Add a mock user with one package. Must be called before * {@link AppHibernationService#onBootPhase(int)} to work properly. * Add a mock user with one package. */ private void addUser(int userId) throws RemoteException { addUser(userId, new String[]{PACKAGE_NAME_1}); private UserInfo addUser(int userId) throws RemoteException { return addUser(userId, new String[]{PACKAGE_NAME_1}); } /** * Add a mock user with the packages specified. Must be called before * {@link AppHibernationService#onBootPhase(int)} to work properly * Add a mock user with the packages specified. */ private void addUser(int userId, String[] packageNames) throws RemoteException { mUserInfos.add(new UserInfo(userId, "user_" + userId, 0 /* flags */)); private UserInfo addUser(int userId, String[] packageNames) throws RemoteException { UserInfo userInfo = new UserInfo(userId, "user_" + userId, 0 /* flags */); mUserInfos.add(userInfo); List<PackageInfo> userPackages = new ArrayList<>(); for (String pkgName : packageNames) { userPackages.add(makePackageInfo(pkgName)); } doReturn(new ParceledListSlice<>(userPackages)).when(mIPackageManager) .getInstalledPackages(anyInt(), eq(userId)); return userInfo; } private static PackageInfo makePackageInfo(String packageName) { Loading Loading
services/core/java/com/android/server/apphibernation/AppHibernationService.java +20 −38 Original line number Diff line number Diff line Loading @@ -18,8 +18,6 @@ package com.android.server.apphibernation; import static android.content.Intent.ACTION_PACKAGE_ADDED; import static android.content.Intent.ACTION_PACKAGE_REMOVED; import static android.content.Intent.ACTION_USER_ADDED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_REMOVED_FOR_ALL_USERS; import static android.content.Intent.EXTRA_REPLACING; import static android.content.pm.PackageManager.MATCH_ALL; Loading @@ -36,7 +34,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.UserInfo; import android.os.Binder; import android.os.RemoteException; import android.os.ResultReceiver; Loading @@ -48,6 +45,7 @@ import android.os.UserManager; import android.provider.DeviceConfig; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; Loading Loading @@ -107,11 +105,6 @@ public final class AppHibernationService extends SystemService { final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ACTION_USER_ADDED); intentFilter.addAction(ACTION_USER_REMOVED); userAllContext.registerReceiver(mBroadcastReceiver, intentFilter); intentFilter = new IntentFilter(); intentFilter.addAction(ACTION_PACKAGE_ADDED); intentFilter.addAction(ACTION_PACKAGE_REMOVED); intentFilter.addDataScheme("package"); Loading @@ -123,19 +116,6 @@ public final class AppHibernationService extends SystemService { publishBinderService(Context.APP_HIBERNATION_SERVICE, mServiceStub); } @Override public void onBootPhase(int phase) { if (phase == PHASE_BOOT_COMPLETED) { synchronized (mLock) { final List<UserInfo> users = mUserManager.getUsers(); // TODO: Pull from persistent disk storage. For now, just make from scratch. for (UserInfo user : users) { addUserPackageStatesL(user.id); } } } } /** * Whether a package is hibernating for a given user. * Loading @@ -145,11 +125,13 @@ public final class AppHibernationService extends SystemService { */ boolean isHibernatingForUser(String packageName, int userId) { userId = handleIncomingUser(userId, "isHibernating"); if (!mUserManager.isUserUnlockingOrUnlocked(userId)) { Slog.e(TAG, "Attempt to get hibernation state of stopped or nonexistent user " + userId); return false; } synchronized (mLock) { final Map<String, UserPackageState> packageStates = mUserStates.get(userId); if (packageStates == null) { throw new IllegalArgumentException("No user associated with user id " + userId); } final UserPackageState pkgState = packageStates.get(packageName); if (pkgState == null) { throw new IllegalArgumentException( Loading Loading @@ -181,10 +163,12 @@ public final class AppHibernationService extends SystemService { */ void setHibernatingForUser(String packageName, int userId, boolean isHibernating) { userId = handleIncomingUser(userId, "setHibernating"); synchronized (mLock) { if (!mUserStates.contains(userId)) { throw new IllegalArgumentException("No user associated with user id " + userId); if (!mUserManager.isUserUnlockingOrUnlocked(userId)) { Slog.w(TAG, "Attempt to set hibernation state for a stopped or nonexistent user " + userId); return; } synchronized (mLock) { Map<String, UserPackageState> packageStates = mUserStates.get(userId); UserPackageState pkgState = packageStates.get(packageName); if (pkgState == null) { Loading Loading @@ -310,15 +294,19 @@ public final class AppHibernationService extends SystemService { mUserStates.put(userId, packages); } private void onUserAdded(int userId) { @Override public void onUserUnlocking(@NonNull TargetUser user) { // TODO: Pull from persistent disk storage. For now, just make from scratch. synchronized (mLock) { addUserPackageStatesL(userId); addUserPackageStatesL(user.getUserIdentifier()); } } private void onUserRemoved(int userId) { @Override public void onUserStopping(@NonNull TargetUser user) { synchronized (mLock) { mUserStates.remove(userId); // TODO: Flush to disk when persistence is implemented mUserStates.remove(user.getUserIdentifier()); } } Loading Loading @@ -395,7 +383,7 @@ public final class AppHibernationService extends SystemService { } } // Broadcast receiver for user and package add/removal events // Broadcast receiver for package add/removal events private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Loading @@ -405,12 +393,6 @@ public final class AppHibernationService extends SystemService { } final String action = intent.getAction(); if (ACTION_USER_ADDED.equals(action)) { onUserAdded(userId); } if (ACTION_USER_REMOVED.equals(action)) { onUserRemoved(userId); } if (ACTION_PACKAGE_ADDED.equals(action) || ACTION_PACKAGE_REMOVED.equals(action)) { final String packageName = intent.getData().getSchemeSpecificPart(); if (intent.getBooleanExtra(EXTRA_REPLACING, false)) { Loading
services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java +20 −27 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import static org.mockito.internal.verification.VerificationModeFactory.times; import android.app.IActivityManager; import android.content.BroadcastReceiver; Loading Loading @@ -87,7 +86,7 @@ public final class AppHibernationServiceTest { mAppHibernationService = new AppHibernationService(mContext, mIPackageManager, mIActivityManager, mUserManager); verify(mContext, times(2)).registerReceiver(mReceiverCaptor.capture(), any()); verify(mContext).registerReceiver(mReceiverCaptor.capture(), any()); mBroadcastReceiver = mReceiverCaptor.getValue(); doReturn(mUserInfos).when(mUserManager).getUsers(); Loading @@ -95,12 +94,13 @@ public final class AppHibernationServiceTest { doAnswer(returnsArgAt(2)).when(mIActivityManager).handleIncomingUser(anyInt(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any(), any()); addUser(USER_ID_1); mAppHibernationService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); UserInfo userInfo = addUser(USER_ID_1); mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(userInfo)); doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_1); } @Test public void testSetHibernatingForUser_packageIsHibernating() throws RemoteException { public void testSetHibernatingForUser_packageIsHibernating() { // WHEN we hibernate a package for a user mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true); Loading @@ -109,8 +109,7 @@ public final class AppHibernationServiceTest { } @Test public void testSetHibernatingForUser_newPackageAdded_packageIsHibernating() throws RemoteException { public void testSetHibernatingForUser_newPackageAdded_packageIsHibernating() { // WHEN a new package is added and it is hibernated Intent intent = new Intent(Intent.ACTION_PACKAGE_ADDED, Uri.fromParts(PACKAGE_SCHEME, PACKAGE_NAME_2, null /* fragment */)); Loading @@ -124,17 +123,12 @@ public final class AppHibernationServiceTest { } @Test public void testSetHibernatingForUser_newUserAdded_packageIsHibernating() public void testSetHibernatingForUser_newUserUnlocked_packageIsHibernating() throws RemoteException { // WHEN a new user is added and a package from the user is hibernated List<PackageInfo> userPackages = new ArrayList<>(); userPackages.add(makePackageInfo(PACKAGE_NAME_1)); doReturn(new ParceledListSlice<>(userPackages)).when(mIPackageManager) .getInstalledPackages(anyInt(), eq(USER_ID_2)); Intent intent = new Intent(Intent.ACTION_USER_ADDED); intent.putExtra(Intent.EXTRA_USER_HANDLE, USER_ID_2); mBroadcastReceiver.onReceive(mContext, intent); UserInfo user2 = addUser(USER_ID_2); mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(user2)); doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_2); mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_2, true); // THEN the new user's package is hibernated Loading @@ -142,8 +136,7 @@ public final class AppHibernationServiceTest { } @Test public void testIsHibernatingForUser_packageReplaced_stillReturnsHibernating() throws RemoteException { public void testIsHibernatingForUser_packageReplaced_stillReturnsHibernating() { // GIVEN a package is currently hibernated mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true); Loading @@ -159,7 +152,7 @@ public final class AppHibernationServiceTest { } @Test public void testSetHibernatingGlobally_packageIsHibernatingGlobally() throws RemoteException { public void testSetHibernatingGlobally_packageIsHibernatingGlobally() { // WHEN we hibernate a package mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true); Loading @@ -168,25 +161,25 @@ public final class AppHibernationServiceTest { } /** * Add a mock user with one package. Must be called before * {@link AppHibernationService#onBootPhase(int)} to work properly. * Add a mock user with one package. */ private void addUser(int userId) throws RemoteException { addUser(userId, new String[]{PACKAGE_NAME_1}); private UserInfo addUser(int userId) throws RemoteException { return addUser(userId, new String[]{PACKAGE_NAME_1}); } /** * Add a mock user with the packages specified. Must be called before * {@link AppHibernationService#onBootPhase(int)} to work properly * Add a mock user with the packages specified. */ private void addUser(int userId, String[] packageNames) throws RemoteException { mUserInfos.add(new UserInfo(userId, "user_" + userId, 0 /* flags */)); private UserInfo addUser(int userId, String[] packageNames) throws RemoteException { UserInfo userInfo = new UserInfo(userId, "user_" + userId, 0 /* flags */); mUserInfos.add(userInfo); List<PackageInfo> userPackages = new ArrayList<>(); for (String pkgName : packageNames) { userPackages.add(makePackageInfo(pkgName)); } doReturn(new ParceledListSlice<>(userPackages)).when(mIPackageManager) .getInstalledPackages(anyInt(), eq(userId)); return userInfo; } private static PackageInfo makePackageInfo(String packageName) { Loading