Merge "Introduce global package hibernation"
This commit is contained in:
@@ -1415,8 +1415,10 @@ package android.app.usage {
|
||||
package android.apphibernation {
|
||||
|
||||
public final class AppHibernationManager {
|
||||
method public boolean isHibernating(@NonNull String);
|
||||
method public void setHibernating(@NonNull String, boolean);
|
||||
method public boolean isHibernatingForUser(@NonNull String);
|
||||
method public boolean isHibernatingGlobally(@NonNull String);
|
||||
method public void setHibernatingForUser(@NonNull String, boolean);
|
||||
method public void setHibernatingGlobally(@NonNull String, boolean);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -49,31 +49,61 @@ public final class AppHibernationManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the package is hibernating, false otherwise.
|
||||
* Returns true if the package is hibernating for this context's user, false otherwise.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public boolean isHibernating(@NonNull String packageName) {
|
||||
public boolean isHibernatingForUser(@NonNull String packageName) {
|
||||
try {
|
||||
return mIAppHibernationService.isHibernating(packageName, mContext.getUserId());
|
||||
return mIAppHibernationService.isHibernatingForUser(packageName, mContext.getUserId());
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the package is hibernating.
|
||||
* Set whether the package is hibernating for this context's user.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public void setHibernating(@NonNull String packageName, boolean isHibernating) {
|
||||
public void setHibernatingForUser(@NonNull String packageName, boolean isHibernating) {
|
||||
try {
|
||||
mIAppHibernationService.setHibernating(packageName, mContext.getUserId(),
|
||||
mIAppHibernationService.setHibernatingForUser(packageName, mContext.getUserId(),
|
||||
isHibernating);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if app is hibernating globally / at the package level.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public boolean isHibernatingGlobally(@NonNull String packageName) {
|
||||
try {
|
||||
return mIAppHibernationService.isHibernatingGlobally(packageName);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether a package should be globally hibernating. This hibernates the package at a
|
||||
* package level. User-level hibernation (e.g.. {@link #isHibernatingForUser} is independent
|
||||
* from global hibernation.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public void setHibernatingGlobally(@NonNull String packageName, boolean isHibernating) {
|
||||
try {
|
||||
mIAppHibernationService.setHibernatingGlobally(packageName, isHibernating);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ package android.apphibernation;
|
||||
* @hide
|
||||
*/
|
||||
interface IAppHibernationService {
|
||||
boolean isHibernating(String packageName, int userId);
|
||||
void setHibernating(String packageName, int userId, boolean isHibernating);
|
||||
boolean isHibernatingForUser(String packageName, int userId);
|
||||
void setHibernatingForUser(String packageName, int userId, boolean isHibernating);
|
||||
boolean isHibernatingGlobally(String packageName);
|
||||
void setHibernatingGlobally(String packageName, boolean isHibernating);
|
||||
}
|
||||
@@ -20,6 +20,7 @@ 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;
|
||||
import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION;
|
||||
@@ -46,6 +47,7 @@ import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
@@ -55,6 +57,7 @@ import com.android.server.SystemService;
|
||||
import java.io.FileDescriptor;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* System service that manages app hibernation state, a state apps can enter that means they are
|
||||
@@ -74,6 +77,8 @@ public final class AppHibernationService extends SystemService {
|
||||
private final UserManager mUserManager;
|
||||
@GuardedBy("mLock")
|
||||
private final SparseArray<Map<String, UserPackageState>> mUserStates = new SparseArray<>();
|
||||
@GuardedBy("mLock")
|
||||
private final Set<String> mGloballyHibernatedPackages = new ArraySet<>();
|
||||
|
||||
/**
|
||||
* Initializes the system service.
|
||||
@@ -138,7 +143,7 @@ public final class AppHibernationService extends SystemService {
|
||||
* @param userId the user to check
|
||||
* @return true if package is hibernating for the user
|
||||
*/
|
||||
public boolean isHibernating(String packageName, int userId) {
|
||||
boolean isHibernatingForUser(String packageName, int userId) {
|
||||
userId = handleIncomingUser(userId, "isHibernating");
|
||||
synchronized (mLock) {
|
||||
final Map<String, UserPackageState> packageStates = mUserStates.get(userId);
|
||||
@@ -151,7 +156,19 @@ public final class AppHibernationService extends SystemService {
|
||||
String.format("Package %s is not installed for user %s",
|
||||
packageName, userId));
|
||||
}
|
||||
return pkgState != null ? pkgState.hibernated : null;
|
||||
return pkgState.hibernated;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a package is hibernated globally. This only occurs when a package is hibernating for
|
||||
* all users and allows us to make optimizations at the package or APK level.
|
||||
*
|
||||
* @param packageName package to check
|
||||
*/
|
||||
boolean isHibernatingGlobally(String packageName) {
|
||||
synchronized (mLock) {
|
||||
return mGloballyHibernatedPackages.contains(packageName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +179,7 @@ public final class AppHibernationService extends SystemService {
|
||||
* @param userId user
|
||||
* @param isHibernating new hibernation state
|
||||
*/
|
||||
public void setHibernating(String packageName, int userId, boolean isHibernating) {
|
||||
void setHibernatingForUser(String packageName, int userId, boolean isHibernating) {
|
||||
userId = handleIncomingUser(userId, "setHibernating");
|
||||
synchronized (mLock) {
|
||||
if (!mUserStates.contains(userId)) {
|
||||
@@ -180,31 +197,98 @@ public final class AppHibernationService extends SystemService {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (isHibernating) {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "hibernatePackage");
|
||||
mIActivityManager.forceStopPackage(packageName, userId);
|
||||
mIPackageManager.deleteApplicationCacheFilesAsUser(packageName, userId,
|
||||
null /* observer */);
|
||||
} else {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackage");
|
||||
mIPackageManager.setPackageStoppedState(packageName, false, userId);
|
||||
}
|
||||
pkgState.hibernated = isHibernating;
|
||||
} catch (RemoteException e) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to hibernate due to manager not being available", e);
|
||||
} finally {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
if (isHibernating) {
|
||||
hibernatePackageForUserL(packageName, userId, pkgState);
|
||||
} else {
|
||||
unhibernatePackageForUserL(packageName, userId, pkgState);
|
||||
}
|
||||
|
||||
// TODO: Support package level hibernation when package is hibernating for all users
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the package should be hibernated globally at a package level, allowing the
|
||||
* the system to make optimizations at the package or APK level.
|
||||
*
|
||||
* @param packageName package to hibernate globally
|
||||
* @param isHibernating new hibernation state
|
||||
*/
|
||||
void setHibernatingGlobally(String packageName, boolean isHibernating) {
|
||||
if (isHibernating != mGloballyHibernatedPackages.contains(packageName)) {
|
||||
synchronized (mLock) {
|
||||
if (isHibernating) {
|
||||
hibernatePackageGloballyL(packageName);
|
||||
} else {
|
||||
unhibernatePackageGloballyL(packageName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put an app into hibernation for a given user, allowing user-level optimizations to occur.
|
||||
* The caller should hold {@link #mLock}
|
||||
*
|
||||
* @param pkgState package hibernation state
|
||||
*/
|
||||
private void hibernatePackageForUserL(@NonNull String packageName, int userId,
|
||||
@NonNull UserPackageState pkgState) {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "hibernatePackage");
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mIActivityManager.forceStopPackage(packageName, userId);
|
||||
mIPackageManager.deleteApplicationCacheFilesAsUser(packageName, userId,
|
||||
null /* observer */);
|
||||
pkgState.hibernated = true;
|
||||
} catch (RemoteException e) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to hibernate due to manager not being available", e);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a package from hibernation for a given user. The caller should hold {@link #mLock}.
|
||||
*
|
||||
* @param pkgState package hibernation state
|
||||
*/
|
||||
private void unhibernatePackageForUserL(@NonNull String packageName, int userId,
|
||||
UserPackageState pkgState) {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackage");
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mIPackageManager.setPackageStoppedState(packageName, false, userId);
|
||||
pkgState.hibernated = false;
|
||||
} catch (RemoteException e) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to unhibernate due to manager not being available", e);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a package into global hibernation, optimizing its storage at a package / APK level.
|
||||
* The caller should hold {@link #mLock}.
|
||||
*/
|
||||
private void hibernatePackageGloballyL(@NonNull String packageName) {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "hibernatePackageGlobally");
|
||||
// TODO(175830194): Delete vdex/odex when DexManager API is built out
|
||||
mGloballyHibernatedPackages.add(packageName);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unhibernate a package from global hibernation. The caller should hold {@link #mLock}.
|
||||
*/
|
||||
private void unhibernatePackageGloballyL(@NonNull String packageName) {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackageGlobally");
|
||||
mGloballyHibernatedPackages.remove(packageName);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates {@link #mUserStates} with the users installed packages. The caller should hold
|
||||
* {@link #mLock}.
|
||||
@@ -220,8 +304,8 @@ public final class AppHibernationService extends SystemService {
|
||||
throw new IllegalStateException("Package manager not available.", e);
|
||||
}
|
||||
|
||||
for (PackageInfo pkg : packageList) {
|
||||
packages.put(pkg.packageName, new UserPackageState());
|
||||
for (int i = 0, size = packageList.size(); i < size; i++) {
|
||||
packages.put(packageList.get(i).packageName, new UserPackageState());
|
||||
}
|
||||
mUserStates.put(userId, packages);
|
||||
}
|
||||
@@ -250,6 +334,12 @@ public final class AppHibernationService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private void onPackageRemovedForAllUsers(@NonNull String packageName) {
|
||||
synchronized (mLock) {
|
||||
mGloballyHibernatedPackages.remove(packageName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Private helper method to get the real user id and enforce permission checks.
|
||||
*
|
||||
@@ -277,13 +367,23 @@ public final class AppHibernationService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHibernating(String packageName, int userId) {
|
||||
return mService.isHibernating(packageName, userId);
|
||||
public boolean isHibernatingForUser(String packageName, int userId) {
|
||||
return mService.isHibernatingForUser(packageName, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHibernating(String packageName, int userId, boolean isHibernating) {
|
||||
mService.setHibernating(packageName, userId, isHibernating);
|
||||
public void setHibernatingForUser(String packageName, int userId, boolean isHibernating) {
|
||||
mService.setHibernatingForUser(packageName, userId, isHibernating);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHibernatingGlobally(String packageName, boolean isHibernating) {
|
||||
mService.setHibernatingGlobally(packageName, isHibernating);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHibernatingGlobally(String packageName) {
|
||||
return mService.isHibernatingGlobally(packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -322,6 +422,9 @@ public final class AppHibernationService extends SystemService {
|
||||
onPackageAdded(packageName, userId);
|
||||
} else if (ACTION_PACKAGE_REMOVED.equals(action)) {
|
||||
onPackageRemoved(packageName, userId);
|
||||
if (intent.getBooleanExtra(EXTRA_REMOVED_FOR_ALL_USERS, false)) {
|
||||
onPackageRemovedForAllUsers(packageName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.android.server.apphibernation;
|
||||
|
||||
import android.os.ShellCommand;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
@@ -27,6 +26,7 @@ import java.io.PrintWriter;
|
||||
*/
|
||||
final class AppHibernationShellCommand extends ShellCommand {
|
||||
private static final String USER_OPT = "--user";
|
||||
private static final String GLOBAL_OPT = "--global";
|
||||
private static final int SUCCESS = 0;
|
||||
private static final int ERROR = -1;
|
||||
private final AppHibernationService mService;
|
||||
@@ -51,7 +51,21 @@ final class AppHibernationShellCommand extends ShellCommand {
|
||||
}
|
||||
|
||||
private int runSetState() {
|
||||
int userId = parseUserOption();
|
||||
String opt;
|
||||
boolean setsGlobal = false;
|
||||
int userId = UserHandle.USER_CURRENT;
|
||||
while ((opt = getNextOption()) != null) {
|
||||
switch (opt) {
|
||||
case USER_OPT:
|
||||
userId = UserHandle.parseUserArg(getNextArgRequired());
|
||||
break;
|
||||
case GLOBAL_OPT:
|
||||
setsGlobal = true;
|
||||
break;
|
||||
default:
|
||||
getErrPrintWriter().println("Error: Unknown option: " + opt);
|
||||
}
|
||||
}
|
||||
|
||||
String pkg = getNextArgRequired();
|
||||
if (pkg == null) {
|
||||
@@ -66,32 +80,43 @@ final class AppHibernationShellCommand extends ShellCommand {
|
||||
}
|
||||
boolean newState = Boolean.parseBoolean(newStateRaw);
|
||||
|
||||
mService.setHibernating(pkg, userId, newState);
|
||||
if (setsGlobal) {
|
||||
mService.setHibernatingGlobally(pkg, newState);
|
||||
} else {
|
||||
mService.setHibernatingForUser(pkg, userId, newState);
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
private int runGetState() {
|
||||
int userId = parseUserOption();
|
||||
String opt;
|
||||
boolean requestsGlobal = false;
|
||||
int userId = UserHandle.USER_CURRENT;
|
||||
while ((opt = getNextOption()) != null) {
|
||||
switch (opt) {
|
||||
case USER_OPT:
|
||||
userId = UserHandle.parseUserArg(getNextArgRequired());
|
||||
break;
|
||||
case GLOBAL_OPT:
|
||||
requestsGlobal = true;
|
||||
break;
|
||||
default:
|
||||
getErrPrintWriter().println("Error: Unknown option: " + opt);
|
||||
}
|
||||
}
|
||||
|
||||
String pkg = getNextArgRequired();
|
||||
if (pkg == null) {
|
||||
getErrPrintWriter().println("Error: No package specified");
|
||||
return ERROR;
|
||||
}
|
||||
boolean isHibernating = mService.isHibernating(pkg, userId);
|
||||
boolean isHibernating = requestsGlobal
|
||||
? mService.isHibernatingGlobally(pkg) : mService.isHibernatingForUser(pkg, userId);
|
||||
final PrintWriter pw = getOutPrintWriter();
|
||||
pw.println(isHibernating);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
private int parseUserOption() {
|
||||
String option = getNextOption();
|
||||
if (TextUtils.equals(option, USER_OPT)) {
|
||||
return UserHandle.parseUserArg(getNextArgRequired());
|
||||
}
|
||||
return UserHandle.USER_CURRENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHelp() {
|
||||
final PrintWriter pw = getOutPrintWriter();
|
||||
@@ -99,11 +124,13 @@ final class AppHibernationShellCommand extends ShellCommand {
|
||||
pw.println(" help");
|
||||
pw.println(" Print this help text.");
|
||||
pw.println("");
|
||||
pw.println(" set-state [--user USER_ID] PACKAGE true|false");
|
||||
pw.println(" Sets the hibernation state of the package to value specified");
|
||||
pw.println(" set-state [--user USER_ID] [--global] PACKAGE true|false");
|
||||
pw.println(" Sets the hibernation state of the package to value specified. Optionally");
|
||||
pw.println(" may specify a user id or set global hibernation state.");
|
||||
pw.println("");
|
||||
pw.println(" get-state [--user USER_ID] PACKAGE");
|
||||
pw.println(" Gets the hibernation state of the package");
|
||||
pw.println(" get-state [--user USER_ID] [--global] PACKAGE");
|
||||
pw.println(" Gets the hibernation state of the package. Optionally may specify a user");
|
||||
pw.println(" id or request global hibernation state.");
|
||||
pw.println("");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,8 @@ public final class AppHibernationServiceTest {
|
||||
private static final int USER_ID_1 = 1;
|
||||
private static final int USER_ID_2 = 2;
|
||||
|
||||
private final List<UserInfo> mUserInfos = new ArrayList<>();
|
||||
|
||||
private AppHibernationService mAppHibernationService;
|
||||
private BroadcastReceiver mBroadcastReceiver;
|
||||
@Mock
|
||||
@@ -88,47 +90,42 @@ public final class AppHibernationServiceTest {
|
||||
verify(mContext, times(2)).registerReceiver(mReceiverCaptor.capture(), any());
|
||||
mBroadcastReceiver = mReceiverCaptor.getValue();
|
||||
|
||||
List<UserInfo> userList = new ArrayList<>();
|
||||
userList.add(new UserInfo(USER_ID_1, "user 1", 0 /* flags */));
|
||||
doReturn(userList).when(mUserManager).getUsers();
|
||||
|
||||
List<PackageInfo> userPackages = new ArrayList<>();
|
||||
userPackages.add(makePackageInfo(PACKAGE_NAME_1));
|
||||
|
||||
doReturn(new ParceledListSlice<>(userPackages)).when(mIPackageManager)
|
||||
.getInstalledPackages(anyInt(), eq(USER_ID_1));
|
||||
doReturn(mUserInfos).when(mUserManager).getUsers();
|
||||
|
||||
doAnswer(returnsArgAt(2)).when(mIActivityManager).handleIncomingUser(anyInt(), anyInt(),
|
||||
anyInt(), anyBoolean(), anyBoolean(), any(), any());
|
||||
|
||||
addUser(USER_ID_1);
|
||||
mAppHibernationService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetHibernating_packageIsHibernating() {
|
||||
public void testSetHibernatingForUser_packageIsHibernating() throws RemoteException {
|
||||
// WHEN we hibernate a package for a user
|
||||
mAppHibernationService.setHibernating(PACKAGE_NAME_1, USER_ID_1, true);
|
||||
mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true);
|
||||
|
||||
// THEN the package is marked hibernating for the user
|
||||
assertTrue(mAppHibernationService.isHibernating(PACKAGE_NAME_1, USER_ID_1));
|
||||
assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetHibernating_newPackageAdded_packageIsHibernating() {
|
||||
public void testSetHibernatingForUser_newPackageAdded_packageIsHibernating()
|
||||
throws RemoteException {
|
||||
// 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 */));
|
||||
intent.putExtra(Intent.EXTRA_USER_HANDLE, USER_ID_1);
|
||||
mBroadcastReceiver.onReceive(mContext, intent);
|
||||
|
||||
mAppHibernationService.setHibernating(PACKAGE_NAME_2, USER_ID_1, true);
|
||||
mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_2, USER_ID_1, true);
|
||||
|
||||
// THEN the new package is hibernated
|
||||
assertTrue(mAppHibernationService.isHibernating(PACKAGE_NAME_2, USER_ID_1));
|
||||
assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_2, USER_ID_1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetHibernating_newUserAdded_packageIsHibernating() throws RemoteException {
|
||||
public void testSetHibernatingForUser_newUserAdded_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));
|
||||
@@ -138,16 +135,17 @@ public final class AppHibernationServiceTest {
|
||||
intent.putExtra(Intent.EXTRA_USER_HANDLE, USER_ID_2);
|
||||
mBroadcastReceiver.onReceive(mContext, intent);
|
||||
|
||||
mAppHibernationService.setHibernating(PACKAGE_NAME_1, USER_ID_2, true);
|
||||
mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_2, true);
|
||||
|
||||
// THEN the new user's package is hibernated
|
||||
assertTrue(mAppHibernationService.isHibernating(PACKAGE_NAME_1, USER_ID_2));
|
||||
assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsHibernating_packageReplaced_stillReturnsHibernating() {
|
||||
public void testIsHibernatingForUser_packageReplaced_stillReturnsHibernating()
|
||||
throws RemoteException {
|
||||
// GIVEN a package is currently hibernated
|
||||
mAppHibernationService.setHibernating(PACKAGE_NAME_1, USER_ID_1, true);
|
||||
mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true);
|
||||
|
||||
// WHEN the package is removed but marked as replacing
|
||||
Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED,
|
||||
@@ -157,7 +155,38 @@ public final class AppHibernationServiceTest {
|
||||
mBroadcastReceiver.onReceive(mContext, intent);
|
||||
|
||||
// THEN the package is still hibernating
|
||||
assertTrue(mAppHibernationService.isHibernating(PACKAGE_NAME_1, USER_ID_1));
|
||||
assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetHibernatingGlobally_packageIsHibernatingGlobally() throws RemoteException {
|
||||
// WHEN we hibernate a package
|
||||
mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true);
|
||||
|
||||
// THEN the package is marked hibernating for the user
|
||||
assertTrue(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mock user with one package. Must be called before
|
||||
* {@link AppHibernationService#onBootPhase(int)} to work properly.
|
||||
*/
|
||||
private void addUser(int userId) throws RemoteException {
|
||||
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
|
||||
*/
|
||||
private void addUser(int userId, String[] packageNames) throws RemoteException {
|
||||
mUserInfos.add(new UserInfo(userId, "user_" + userId, 0 /* flags */));
|
||||
List<PackageInfo> userPackages = new ArrayList<>();
|
||||
for (String pkgName : packageNames) {
|
||||
userPackages.add(makePackageInfo(pkgName));
|
||||
}
|
||||
doReturn(new ParceledListSlice<>(userPackages)).when(mIPackageManager)
|
||||
.getInstalledPackages(anyInt(), eq(userId));
|
||||
}
|
||||
|
||||
private static PackageInfo makePackageInfo(String packageName) {
|
||||
|
||||
Reference in New Issue
Block a user