Move AppHibernationServices dependencies to injector
Similar to other system services, we move AppHibernationService's dependencies to an injector class that can be mocked for testing so that we minimize side-effects in unit tests Also, add @GuardedBy annotations instead of having an L at the end of method names since this is exactly what the annotation is for. Bug: 175829330 Test: atest AppHibernationServiceTest Change-Id: Iec51a349ff898923bacf6040c3ebccefa8831a68
This commit is contained in:
@@ -88,19 +88,16 @@ public final class AppHibernationService extends SystemService {
|
||||
* @param context The system server context.
|
||||
*/
|
||||
public AppHibernationService(@NonNull Context context) {
|
||||
this(context, IPackageManager.Stub.asInterface(ServiceManager.getService("package")),
|
||||
ActivityManager.getService(),
|
||||
context.getSystemService(UserManager.class));
|
||||
this(new InjectorImpl(context));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
AppHibernationService(@NonNull Context context, IPackageManager packageManager,
|
||||
IActivityManager activityManager, UserManager userManager) {
|
||||
super(context);
|
||||
mContext = context;
|
||||
mIPackageManager = packageManager;
|
||||
mIActivityManager = activityManager;
|
||||
mUserManager = userManager;
|
||||
AppHibernationService(@NonNull Injector injector) {
|
||||
super(injector.getContext());
|
||||
mContext = injector.getContext();
|
||||
mIPackageManager = injector.getPackageManager();
|
||||
mIActivityManager = injector.getActivityManager();
|
||||
mUserManager = injector.getUserManager();
|
||||
|
||||
final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
|
||||
|
||||
@@ -182,9 +179,9 @@ public final class AppHibernationService extends SystemService {
|
||||
}
|
||||
|
||||
if (isHibernating) {
|
||||
hibernatePackageForUserL(packageName, userId, pkgState);
|
||||
hibernatePackageForUser(packageName, userId, pkgState);
|
||||
} else {
|
||||
unhibernatePackageForUserL(packageName, userId, pkgState);
|
||||
unhibernatePackageForUser(packageName, userId, pkgState);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -200,9 +197,9 @@ public final class AppHibernationService extends SystemService {
|
||||
if (isHibernating != mGloballyHibernatedPackages.contains(packageName)) {
|
||||
synchronized (mLock) {
|
||||
if (isHibernating) {
|
||||
hibernatePackageGloballyL(packageName);
|
||||
hibernatePackageGlobally(packageName);
|
||||
} else {
|
||||
unhibernatePackageGloballyL(packageName);
|
||||
unhibernatePackageGlobally(packageName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,11 +207,11 @@ public final class AppHibernationService extends SystemService {
|
||||
|
||||
/**
|
||||
* 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,
|
||||
@GuardedBy("mLock")
|
||||
private void hibernatePackageForUser(@NonNull String packageName, int userId,
|
||||
@NonNull UserPackageState pkgState) {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "hibernatePackage");
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
@@ -233,11 +230,12 @@ public final class AppHibernationService extends SystemService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a package from hibernation for a given user. The caller should hold {@link #mLock}.
|
||||
* Remove a package from hibernation for a given user.
|
||||
*
|
||||
* @param pkgState package hibernation state
|
||||
*/
|
||||
private void unhibernatePackageForUserL(@NonNull String packageName, int userId,
|
||||
@GuardedBy("mLock")
|
||||
private void unhibernatePackageForUser(@NonNull String packageName, int userId,
|
||||
UserPackageState pkgState) {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackage");
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
@@ -255,9 +253,9 @@ public final class AppHibernationService extends SystemService {
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
@GuardedBy("mLock")
|
||||
private void hibernatePackageGlobally(@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);
|
||||
@@ -265,21 +263,22 @@ public final class AppHibernationService extends SystemService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Unhibernate a package from global hibernation. The caller should hold {@link #mLock}.
|
||||
* Unhibernate a package from global hibernation.
|
||||
*/
|
||||
private void unhibernatePackageGloballyL(@NonNull String packageName) {
|
||||
@GuardedBy("mLock")
|
||||
private void unhibernatePackageGlobally(@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}.
|
||||
* Populates {@link #mUserStates} with the users installed packages.
|
||||
*
|
||||
* @param userId user id to add installed packages for
|
||||
*/
|
||||
private void addUserPackageStatesL(int userId) {
|
||||
@GuardedBy("mLock")
|
||||
private void addUserPackageStates(int userId) {
|
||||
Map<String, UserPackageState> packages = new ArrayMap<>();
|
||||
List<PackageInfo> packageList;
|
||||
try {
|
||||
@@ -298,7 +297,7 @@ public final class AppHibernationService extends SystemService {
|
||||
public void onUserUnlocking(@NonNull TargetUser user) {
|
||||
// TODO: Pull from persistent disk storage. For now, just make from scratch.
|
||||
synchronized (mLock) {
|
||||
addUserPackageStatesL(user.getUserIdentifier());
|
||||
addUserPackageStates(user.getUserIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,4 +430,45 @@ public final class AppHibernationService extends SystemService {
|
||||
public boolean hibernated;
|
||||
// TODO: Track whether hibernation is exempted by the user
|
||||
}
|
||||
|
||||
/**
|
||||
* Dependency injector for {@link #AppHibernationService)}.
|
||||
*/
|
||||
interface Injector {
|
||||
Context getContext();
|
||||
|
||||
IPackageManager getPackageManager();
|
||||
|
||||
IActivityManager getActivityManager();
|
||||
|
||||
UserManager getUserManager();
|
||||
}
|
||||
|
||||
private static final class InjectorImpl implements Injector {
|
||||
private final Context mContext;
|
||||
|
||||
InjectorImpl(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPackageManager getPackageManager() {
|
||||
return IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IActivityManager getActivityManager() {
|
||||
return ActivityManager.getService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserManager getUserManager() {
|
||||
return mContext.getSystemService(UserManager.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,8 +83,7 @@ public final class AppHibernationServiceTest {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
doReturn(mContext).when(mContext).createContextAsUser(any(), anyInt());
|
||||
|
||||
mAppHibernationService = new AppHibernationService(mContext, mIPackageManager,
|
||||
mIActivityManager, mUserManager);
|
||||
mAppHibernationService = new AppHibernationService(new MockInjector(mContext));
|
||||
|
||||
verify(mContext).registerReceiver(mReceiverCaptor.capture(), any());
|
||||
mBroadcastReceiver = mReceiverCaptor.getValue();
|
||||
@@ -187,4 +186,32 @@ public final class AppHibernationServiceTest {
|
||||
pkg.packageName = packageName;
|
||||
return pkg;
|
||||
}
|
||||
|
||||
private class MockInjector implements AppHibernationService.Injector {
|
||||
private final Context mContext;
|
||||
|
||||
MockInjector(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IActivityManager getActivityManager() {
|
||||
return mIActivityManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPackageManager getPackageManager() {
|
||||
return mIPackageManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserManager getUserManager() {
|
||||
return mUserManager;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user