summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/system-current.txt2
-rw-r--r--core/api/test-current.txt6
-rw-r--r--core/java/android/app/ActivityManager.java38
-rw-r--r--core/java/android/app/IActivityManager.aidl3
-rw-r--r--core/java/android/content/Intent.java2
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java21
6 files changed, 64 insertions, 8 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 761230f8188a..25cef758af47 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -407,7 +407,7 @@ package android.app {
method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public static void setPersistentVrThread(int);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public boolean startProfile(@NonNull android.os.UserHandle);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public boolean stopProfile(@NonNull android.os.UserHandle);
- method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean switchUser(@NonNull android.os.UserHandle);
+ method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean switchUser(@NonNull android.os.UserHandle);
}
public static interface ActivityManager.OnUidImportanceListener {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index e486fa2c2e29..2f859d73fde4 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -104,7 +104,9 @@ 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(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();
field public static final long DROP_CLOSE_SYSTEM_DIALOGS = 174664120L; // 0xa6929b8L
field public static final long LOCK_DOWN_CLOSE_SYSTEM_DIALOGS = 174664365L; // 0xa692aadL
field public static final int PROCESS_CAPABILITY_ALL = 15; // 0xf
@@ -709,6 +711,10 @@ package android.content {
method public int getDisplayId();
}
+ public class Intent implements java.lang.Cloneable android.os.Parcelable {
+ field public static final String ACTION_USER_STOPPED = "android.intent.action.USER_STOPPED";
+ }
+
public class SyncAdapterType implements android.os.Parcelable {
method @Nullable public String getPackageName();
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index f905ec86aab7..3fedda36de2d 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -31,6 +31,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.annotation.UserIdInt;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
@@ -4048,7 +4049,8 @@ public class ActivityManager {
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
+ android.Manifest.permission.CREATE_USERS})
public boolean switchUser(@NonNull UserHandle user) {
if (user == null) {
throw new IllegalArgumentException("UserHandle cannot be null.");
@@ -4144,6 +4146,25 @@ public class ActivityManager {
}
}
+ /**
+ * Stops the given {@code userId}.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+ public boolean stopUser(@UserIdInt int userId, boolean force) {
+ if (userId == UserHandle.USER_SYSTEM) {
+ return false;
+ }
+ try {
+ return USER_OP_SUCCESS == getService().stopUser(
+ userId, force, /* callback= */ null);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/** {@hide} */
public static final int FLAG_OR_STOPPED = 1 << 0;
/** {@hide} */
@@ -4811,6 +4832,21 @@ public class ActivityManager {
}
/**
+ * Blocks until all broadcast queues become idle.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.DUMP)
+ public void waitForBroadcastIdle() {
+ try {
+ getService().waitForBroadcastIdle();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* A subset of immutable pending intent information suitable for caching on the client side.
*
* @hide
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index ef0dcabbe111..4c2433c04771 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -709,4 +709,7 @@ interface IActivityManager {
ParceledListSlice queryIntentComponentsForIntentSender(in IIntentSender sender, int matchFlags);
int getUidProcessCapabilities(int uid, in String callingPackage);
+
+ /** Blocks until all broadcast queues become idle. */
+ void waitForBroadcastIdle();
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index adf9ff32c4ec..96b8fbe293f5 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -28,6 +28,7 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.app.AppGlobals;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
@@ -3771,6 +3772,7 @@ public class Intent implements Parcelable, Cloneable {
* has just been stopped (which is no longer running).
* @hide
*/
+ @TestApi
public static final String ACTION_USER_STOPPED =
"android.intent.action.USER_STOPPED";
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 83cbf66ecaea..0e8644a6569e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -16147,7 +16147,12 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- public void waitForBroadcastIdle(PrintWriter pw) {
+ @Override
+ public void waitForBroadcastIdle() {
+ waitForBroadcastIdle(/* printWriter= */ null);
+ }
+
+ public void waitForBroadcastIdle(@Nullable PrintWriter pw) {
enforceCallingPermission(permission.DUMP, "waitForBroadcastIdle()");
while (true) {
boolean idle = true;
@@ -16155,9 +16160,11 @@ public class ActivityManagerService extends IActivityManager.Stub
for (BroadcastQueue queue : mBroadcastQueues) {
if (!queue.isIdle()) {
final String msg = "Waiting for queue " + queue + " to become idle...";
- pw.println(msg);
- pw.println(queue.describeState());
- pw.flush();
+ if (pw != null) {
+ pw.println(msg);
+ pw.println(queue.describeState());
+ pw.flush();
+ }
Slog.v(TAG, msg);
queue.cancelDeferrals();
idle = false;
@@ -16167,8 +16174,10 @@ public class ActivityManagerService extends IActivityManager.Stub
if (idle) {
final String msg = "All broadcast queues are idle!";
- pw.println(msg);
- pw.flush();
+ if (pw != null) {
+ pw.println(msg);
+ pw.flush();
+ }
Slog.v(TAG, msg);
return;
} else {