diff options
author | Felipe Leme <felipeal@google.com> | 2021-11-02 15:12:19 -0700 |
---|---|---|
committer | Felipe Leme <felipeal@google.com> | 2021-11-04 12:36:56 -0700 |
commit | 9cab317f2a046c60efc3476b74d6bfa76a894752 (patch) | |
tree | 959780ab797cccef9b022143b168b4f3ed59b6b4 | |
parent | bec1fdfcd099a002d83ce26125270f71ffd5f887 (diff) |
New TestAPIs on ActivityManager to not stop bg users on switch.
Test: atest NeneTest:UsersTest
Test: m update-api
Test: adb shell cmd activity set-stop-user-on-switch false
Test: adb shell cmd activity set-stop-user-on-switch
Test: adb shell dumpsys activity users|grep OnSwitch
Bug: 203752848
Change-Id: Ib57989aff323dc1f7d98720d01215e4f7c79ba3a
7 files changed, 148 insertions, 2 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 488f8b145e52..40880c19f0a0 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -113,6 +113,7 @@ package android.app { method @RequiresPermission(android.Manifest.permission.RESET_APP_ERRORS) public void resetAppErrors(); method public static void resumeAppSwitches() throws android.os.RemoteException; method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void setStopBackgroundUsersOnSwitch(int); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean stopUser(int, boolean); method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String); method @RequiresPermission(android.Manifest.permission.DUMP) public void waitForBroadcastIdle(); @@ -127,6 +128,9 @@ package android.app { field public static final int PROCESS_CAPABILITY_NONE = 0; // 0x0 field public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4; // 0x4 field public static final int PROCESS_STATE_TOP = 2; // 0x2 + field public static final int STOP_BG_USERS_ON_SWITCH_DEFAULT = -1; // 0xffffffff + field public static final int STOP_BG_USERS_ON_SWITCH_FALSE = 0; // 0x0 + field public static final int STOP_BG_USERS_ON_SWITCH_TRUE = 1; // 0x1 } public static class ActivityManager.RunningAppProcessInfo implements android.os.Parcelable { diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index f53c5b6c9748..50a562b66f16 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -4076,6 +4076,56 @@ public class ActivityManager { } /** + * Uses the value defined by the platform. + * + * @hide + */ + @TestApi + public static final int STOP_BG_USERS_ON_SWITCH_DEFAULT = -1; + + /** + * Overrides value defined by the platform and stop background users on switch. + * + * @hide + */ + @TestApi + public static final int STOP_BG_USERS_ON_SWITCH_TRUE = 1; + + /** + * Overrides value defined by the platform and don't stop background users on switch. + * + * @hide + */ + @TestApi + public static final int STOP_BG_USERS_ON_SWITCH_FALSE = 0; + + /** @hide */ + @IntDef(prefix = { "STOP_BG_USERS_ON_SWITCH_" }, value = { + STOP_BG_USERS_ON_SWITCH_DEFAULT, + STOP_BG_USERS_ON_SWITCH_TRUE, + STOP_BG_USERS_ON_SWITCH_FALSE + }) + public @interface StopBgUsersOnSwitch {} + + /** + * Sets whether background users should be stopped when the current user is switched. + * + * <p>Should only be used on tests. + * + * @hide + */ + @TestApi + @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) + public void setStopBackgroundUsersOnSwitch(@StopBgUsersOnSwitch int value) { + try { + getService().setStopBackgroundUsersOnSwitch(value); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** * Starts a profile. * To be used with non-managed profiles, managed profiles should use * {@link UserManager#requestQuietModeEnabled} diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index f8c8aa32a26e..b416c95329b2 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -16,6 +16,8 @@ package android.app; +import static android.app.ActivityManager.StopBgUsersOnSwitch; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; @@ -661,6 +663,11 @@ public abstract class ActivityManagerInternal { @Nullable VoiceInteractionManagerProvider provider); /** + * Sets whether background users should be stopped when the current user is switched. + */ + public abstract void setStopBackgroundUsersOnSwitch(@StopBgUsersOnSwitch int value); + + /** * Provides the interface to communicate between voice interaction manager service and * ActivityManagerService. */ diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index b90b9a11611e..601ec9a152ca 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -341,6 +341,7 @@ interface IActivityManager { @UnsupportedAppUsage boolean switchUser(int userid); @UnsupportedAppUsage + void setStopBackgroundUsersOnSwitch(int value); boolean removeTask(int taskId); @UnsupportedAppUsage void registerProcessObserver(in IProcessObserver observer); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 18ed9586d263..36dcc8dc0183 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -31,6 +31,7 @@ import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY; import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.app.ActivityManager.PROCESS_STATE_TOP; +import static android.app.ActivityManager.StopBgUsersOnSwitch; import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.AppOpsManager.OP_NONE; @@ -15096,6 +15097,11 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override + public void setStopBackgroundUsersOnSwitch(@StopBgUsersOnSwitch int value) { + mUserController.setStopBackgroundUsersOnSwitch(value); + } + + @Override public int stopUser(final int userId, boolean force, final IStopUserCallback callback) { return mUserController.stopUser(userId, force, /* allowDelayedLocking= */ false, /* callback= */ callback, /* keyEvictedCallback= */ null); @@ -16392,6 +16398,11 @@ public class ActivityManagerService extends IActivityManager.Stub @Nullable ActivityManagerInternal.VoiceInteractionManagerProvider provider) { ActivityManagerService.this.setVoiceInteractionManagerProvider(provider); } + + @Override + public void setStopBackgroundUsersOnSwitch(int value) { + ActivityManagerService.this.setStopBackgroundUsersOnSwitch(value); + } } long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) { diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 685d606f8d41..60b2149b1f14 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -29,6 +29,8 @@ import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_CRI import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW; import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_MODERATE; import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_NORMAL; +import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; +import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.LowMemDetector.ADJ_MEM_FACTOR_NOTHING; import android.app.ActivityManager; @@ -100,6 +102,7 @@ import com.android.internal.util.HexDump; import com.android.internal.util.MemInfoReader; import com.android.server.am.LowMemDetector.MemFactor; import com.android.server.compat.PlatformCompat; +import com.android.server.utils.Slogf; import java.io.BufferedReader; import java.io.IOException; @@ -128,6 +131,10 @@ import javax.microedition.khronos.egl.EGLDisplay; import javax.microedition.khronos.egl.EGLSurface; final class ActivityManagerShellCommand extends ShellCommand { + + static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityManagerShellCommand" : TAG_AM; + + public static final String NO_CLASS_ERROR_CODE = "Error type 3"; private static final String SHELL_PACKAGE_NAME = "com.android.shell"; @@ -323,6 +330,8 @@ final class ActivityManagerShellCommand extends ShellCommand { return runServiceRestartBackoff(pw); case "get-isolated-pids": return runGetIsolatedProcesses(pw); + case "set-stop-user-on-switch": + return runSetStopBackgroundUsersOnSwitch(pw); default: return handleDefaultCommands(cmd); } @@ -3157,6 +3166,30 @@ final class ActivityManagerShellCommand extends ShellCommand { return 0; } + private int runSetStopBackgroundUsersOnSwitch(PrintWriter pw) throws RemoteException { + mInternal.enforceCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, + "setStopBackgroundUsersOnSwitch()"); + String arg = getNextArg(); + if (arg == null) { + Slogf.i(TAG, "runSetStopBackgroundUsersOnSwitch(): resetting to default value"); + mInternal.setStopBackgroundUsersOnSwitch( + ActivityManager.STOP_BG_USERS_ON_SWITCH_DEFAULT); + pw.println("Reset to default value"); + return 0; + } + + boolean stop = Boolean.parseBoolean(arg); + int value = stop + ? ActivityManager.STOP_BG_USERS_ON_SWITCH_TRUE + : ActivityManager.STOP_BG_USERS_ON_SWITCH_FALSE; + + Slogf.i(TAG, "runSetStopBackgroundUsersOnSwitch(): setting to %d (%b)", value, stop); + mInternal.setStopBackgroundUsersOnSwitch(value); + pw.println("Set to " + stop); + + return 0; + } + private Resources getResources(PrintWriter pw) throws RemoteException { // system resources does not contain all the device configuration, construct it manually. Configuration config = mInterface.getConfiguration(); @@ -3489,6 +3522,10 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" Shows the restart backoff policy state for <PACKAGE_NAME>."); pw.println(" get-isolated-pids <UID>"); pw.println(" Get the PIDs of isolated processes with packages in this <UID>"); + pw.println(" set-stop-user-on-switch [true|false]"); + pw.println(" Sets whether the current user (and its profiles) should be stopped" + + " when switching to a different user."); + pw.println(" Without arguments, it resets to the value defined by platform."); pw.println(); Intent.printIntentArgsHelp(pw, ""); } diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index ba3e1fb95e7d..b8be6c5f83dd 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -19,6 +19,9 @@ package com.android.server.am; import static android.Manifest.permission.INTERACT_ACROSS_PROFILES; import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; +import static android.app.ActivityManager.STOP_BG_USERS_ON_SWITCH_DEFAULT; +import static android.app.ActivityManager.STOP_BG_USERS_ON_SWITCH_TRUE; +import static android.app.ActivityManager.StopBgUsersOnSwitch; import static android.app.ActivityManager.USER_OP_ERROR_IS_SYSTEM; import static android.app.ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP; import static android.app.ActivityManager.USER_OP_IS_CURRENT; @@ -368,6 +371,13 @@ class UserController implements Handler.Callback { @GuardedBy("mLock") private boolean mInitialized; + /** + * Defines the behavior of whether the background users should be stopped when the foreground + * user is switched. + */ + @GuardedBy("mLock") + private @StopBgUsersOnSwitch int mStopBgUsersOnSwitch = STOP_BG_USERS_ON_SWITCH_DEFAULT; + UserController(ActivityManagerService service) { this(new Injector(service)); } @@ -408,8 +418,33 @@ class UserController implements Handler.Callback { } } + void setStopBackgroundUsersOnSwitch(@StopBgUsersOnSwitch int value) { + if (mInjector.checkCallingPermission(android.Manifest.permission.MANAGE_USERS) + == PackageManager.PERMISSION_DENIED && mInjector.checkCallingPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) + == PackageManager.PERMISSION_DENIED) { + throw new SecurityException( + "You either need MANAGE_USERS or INTERACT_ACROSS_USERS_FULL permission to " + + "call setStopBackgroundUsersOnSwitch()"); + } + + synchronized (mLock) { + Slogf.i(TAG, "setStopBackgroundUsersOnSwitch(): %d -> %d", + mStopBgUsersOnSwitch, value); + mStopBgUsersOnSwitch = value; + } + } + private boolean shouldStopBackgroundUsersOnSwitch() { - int property = SystemProperties.getInt("fw.stop_bg_users_on_switch", -1); + synchronized (mLock) { + if (mStopBgUsersOnSwitch != STOP_BG_USERS_ON_SWITCH_DEFAULT) { + final boolean value = mStopBgUsersOnSwitch == STOP_BG_USERS_ON_SWITCH_TRUE; + Slogf.i(TAG, "isStopBackgroundUsersOnSwitch(): returning overridden value (%b)", + value); + return value; + } + } + final int property = SystemProperties.getInt("fw.stop_bg_users_on_switch", -1); return property == -1 ? mDelayUserDataLocking : property == 1; } @@ -2611,8 +2646,9 @@ class UserController implements Handler.Callback { pw.println(" mTargetUserId:" + mTargetUserId); pw.println(" mLastActiveUsers:" + mLastActiveUsers); pw.println(" mDelayUserDataLocking:" + mDelayUserDataLocking); - pw.println(" shouldStopBackgroundUsersOnSwitch:" + pw.println(" shouldStopBackgroundUsersOnSwitch():" + shouldStopBackgroundUsersOnSwitch()); + pw.println(" mStopBgUsersOnSwitch:" + mStopBgUsersOnSwitch); pw.println(" mMaxRunningUsers:" + mMaxRunningUsers); pw.println(" mUserSwitchUiEnabled:" + mUserSwitchUiEnabled); pw.println(" mInitialized:" + mInitialized); |