diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 58f78aa4fc152..c1f6219025f9c 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -18,6 +18,7 @@ package android.app { public class ActivityManager { method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener); + method @NonNull @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int[] getUidFrozenState(@NonNull int[]); method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void registerUidFrozenStateChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.app.ActivityManager.UidFrozenStateChangedCallback); method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener); method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void unregisterUidFrozenStateChangedCallback(@NonNull android.app.ActivityManager.UidFrozenStateChangedCallback); diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 1a8ebb15663b9..b53eb426f09d2 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -131,6 +131,7 @@ package android.app { method public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName); method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public int[] getDisplayIdsForStartingVisibleBackgroundUsers(); method public long getTotalRam(); + method @NonNull @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int[] getUidFrozenState(@NonNull int[]); method @RequiresPermission(allOf={android.Manifest.permission.PACKAGE_USAGE_STATS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional=true) public int getUidProcessCapabilities(int); method @RequiresPermission(allOf={android.Manifest.permission.PACKAGE_USAGE_STATS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional=true) public int getUidProcessState(int); method public void holdLock(android.os.IBinder, int); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 929c07bc1dc5a..27f4c1716be20 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -362,6 +362,30 @@ public class ActivityManager { } } + /** + * Query the frozen state of a list of UIDs. + * + * @param uids the array of UIDs which the client would like to know the frozen state of. + * @return An array containing the frozen state for each requested UID, by index. Will be set + * to {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_FROZEN} + * if the UID is frozen. If the UID is not frozen or not found, + * {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_UNFROZEN} + * will be set. + * + * @hide + */ + @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @TestApi + public @NonNull @UidFrozenStateChangedCallback.UidFrozenState + int[] getUidFrozenState(@NonNull int[] uids) { + try { + return getService().getUidFrozenState(uids); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * {@code * } name for a 'home' Activity that declares a package that is to be diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 97d45623d3da3..91eb4c44cda5a 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -882,4 +882,6 @@ interface IActivityManager { void registerUidFrozenStateChangedCallback(in IUidFrozenStateChangedCallback callback); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)") void unregisterUidFrozenStateChangedCallback(in IUidFrozenStateChangedCallback callback); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)") + int[] getUidFrozenState(in int[] uids); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 713b993824f9d..8d8ed196be18c 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -38,6 +38,8 @@ 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.StopUserOnSwitch; +import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN; +import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_UNFROZEN; import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.ActivityManagerInternal.MEDIA_PROJECTION_TOKEN_EVENT_CREATED; @@ -7500,9 +7502,9 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void registerUidFrozenStateChangedCallback( @NonNull IUidFrozenStateChangedCallback callback) { + Preconditions.checkNotNull(callback, "callback cannot be null"); enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS, "registerUidFrozenStateChangedCallback()"); - Preconditions.checkNotNull(callback, "callback cannot be null"); synchronized (mUidFrozenStateChangedCallbackList) { final boolean registered = mUidFrozenStateChangedCallbackList.register(callback); if (!registered) { @@ -7520,14 +7522,47 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void unregisterUidFrozenStateChangedCallback( @NonNull IUidFrozenStateChangedCallback callback) { + Preconditions.checkNotNull(callback, "callback cannot be null"); enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS, "unregisterUidFrozenStateChangedCallback()"); - Preconditions.checkNotNull(callback, "callback cannot be null"); synchronized (mUidFrozenStateChangedCallbackList) { mUidFrozenStateChangedCallbackList.unregister(callback); } } + /** + * Query the frozen state of a list of UIDs. + * + * @param uids the array of UIDs which the client would like to know the frozen state of. + * @return An array containing the frozen state for each requested UID, by index. Will be set + * to {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_FROZEN} + * if the UID is frozen. If the UID is not frozen or not found, + * {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_UNFROZEN} + * will be set. + * + * @hide + */ + @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS) + @Override + public @NonNull int[] getUidFrozenState(@NonNull int[] uids) { + Preconditions.checkNotNull(uids, "uid array cannot be null"); + enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS, + "getUidFrozenState()"); + + final int[] frozenStates = new int[uids.length]; + synchronized (mProcLock) { + for (int i = 0; i < uids.length; i++) { + final UidRecord uidRec = mProcessList.mActiveUids.get(uids[i]); + if (uidRec != null && uidRec.areAllProcessesFrozen()) { + frozenStates[i] = UID_FROZEN_STATE_FROZEN; + } else { + frozenStates[i] = UID_FROZEN_STATE_UNFROZEN; + } + } + } + return frozenStates; + } + /** * Notify the system that a UID has been frozen or unfrozen. *