From 23c36dbe21ecd38bb7aa9ebb0d2890865fce79da Mon Sep 17 00:00:00 2001 From: kholoud mohamed Date: Mon, 15 Mar 2021 14:38:02 +0000 Subject: [PATCH] Exposed some testAPIs in ActivityManager - Added the following testAPIs to replace the usage of adb shell commands in tests: * stopUser and ACTION_USER_STOPPED * waitForBroadcastIdle - Changed the documentation for switchUser to correctly reflect that it accepts CREATE_USERS Test: verfied that tests can access the APIs Bug: 181030374 Change-Id: I92b92471a18cf97a118d3f1946d6e06c277a76f1 --- core/api/system-current.txt | 2 +- core/api/test-current.txt | 6 +++ core/java/android/app/ActivityManager.java | 38 ++++++++++++++++++- core/java/android/app/IActivityManager.aidl | 3 ++ core/java/android/content/Intent.java | 2 + .../server/am/ActivityManagerService.java | 21 +++++++--- 6 files changed, 64 insertions(+), 8 deletions(-) diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 761230f8188a1..25cef758af474 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 e486fa2c2e29f..2f859d73fde46 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, 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 f905ec86aab78..3fedda36de2d5 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} */ @@ -4810,6 +4831,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. * diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index ef0dcabbe1111..4c2433c047711 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 adf9ff32c4ece..96b8fbe293f50 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 83cbf66ecaea4..0e8644a6569ef 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 {