Loading core/api/system-current.txt +4 −2 Original line number Diff line number Diff line Loading @@ -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); } } Loading core/java/android/apphibernation/AppHibernationManager.java +36 −6 Original line number Diff line number Diff line Loading @@ -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(); } } } core/java/android/apphibernation/IAppHibernationService.aidl +4 −2 Original line number Diff line number Diff line Loading @@ -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); } No newline at end of file services/core/java/com/android/server/apphibernation/AppHibernationService.java +128 −25 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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 Loading @@ -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. Loading Loading @@ -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); Loading @@ -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); } } Loading @@ -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)) { Loading @@ -180,29 +197,96 @@ public final class AppHibernationService extends SystemService { return; } if (isHibernating) { hibernatePackageForUserL(packageName, userId, pkgState); } else { unhibernatePackageForUserL(packageName, userId, pkgState); } } } final long caller = Binder.clearCallingIdentity(); try { /** * 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 */); } else { Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackage"); mIPackageManager.setPackageStoppedState(packageName, false, userId); } pkgState.hibernated = isHibernating; 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); } } // TODO: Support package level hibernation when package is hibernating for all users /** * 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); } /** Loading @@ -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); } Loading Loading @@ -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. * Loading Loading @@ -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 setHibernatingForUser(String packageName, int userId, boolean isHibernating) { mService.setHibernatingForUser(packageName, userId, isHibernating); } @Override public void setHibernating(String packageName, int userId, boolean isHibernating) { mService.setHibernating(packageName, userId, isHibernating); public void setHibernatingGlobally(String packageName, boolean isHibernating) { mService.setHibernatingGlobally(packageName, isHibernating); } @Override public boolean isHibernatingGlobally(String packageName) { return mService.isHibernatingGlobally(packageName); } @Override Loading Loading @@ -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); } } } } Loading services/core/java/com/android/server/apphibernation/AppHibernationShellCommand.java +44 −17 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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) { Loading @@ -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(); Loading @@ -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(""); } } Loading
core/api/system-current.txt +4 −2 Original line number Diff line number Diff line Loading @@ -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); } } Loading
core/java/android/apphibernation/AppHibernationManager.java +36 −6 Original line number Diff line number Diff line Loading @@ -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(); } } }
core/java/android/apphibernation/IAppHibernationService.aidl +4 −2 Original line number Diff line number Diff line Loading @@ -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); } No newline at end of file
services/core/java/com/android/server/apphibernation/AppHibernationService.java +128 −25 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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 Loading @@ -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. Loading Loading @@ -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); Loading @@ -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); } } Loading @@ -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)) { Loading @@ -180,29 +197,96 @@ public final class AppHibernationService extends SystemService { return; } if (isHibernating) { hibernatePackageForUserL(packageName, userId, pkgState); } else { unhibernatePackageForUserL(packageName, userId, pkgState); } } } final long caller = Binder.clearCallingIdentity(); try { /** * 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 */); } else { Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackage"); mIPackageManager.setPackageStoppedState(packageName, false, userId); } pkgState.hibernated = isHibernating; 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); } } // TODO: Support package level hibernation when package is hibernating for all users /** * 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); } /** Loading @@ -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); } Loading Loading @@ -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. * Loading Loading @@ -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 setHibernatingForUser(String packageName, int userId, boolean isHibernating) { mService.setHibernatingForUser(packageName, userId, isHibernating); } @Override public void setHibernating(String packageName, int userId, boolean isHibernating) { mService.setHibernating(packageName, userId, isHibernating); public void setHibernatingGlobally(String packageName, boolean isHibernating) { mService.setHibernatingGlobally(packageName, isHibernating); } @Override public boolean isHibernatingGlobally(String packageName) { return mService.isHibernatingGlobally(packageName); } @Override Loading Loading @@ -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); } } } } Loading
services/core/java/com/android/server/apphibernation/AppHibernationShellCommand.java +44 −17 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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) { Loading @@ -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(); Loading @@ -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(""); } }