diff options
5 files changed, 82 insertions, 0 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index e3909f965283..0881db039f77 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -518,6 +518,11 @@ public abstract class ActivityManagerInternal { Notification notification, int id, String pkg, @UserIdInt int userId); /** + * Un-foreground all foreground services in the given app. + */ + public abstract void makeServicesNonForeground(String pkg, @UserIdInt int userId); + + /** * If the given app has any FGSs whose notifications are in the given channel, * stop them. */ diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 47e481099045..658c1309b94e 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -278,6 +278,7 @@ interface IActivityManager { List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState(); boolean clearApplicationUserData(in String packageName, boolean keepState, in IPackageDataObserver observer, int userId); + void makeServicesNonForeground(in String packageName, int userId); @UnsupportedAppUsage void forceStopPackage(in String packageName, int userId); boolean killPids(in int[] pids, in String reason, boolean secure); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 1997897046d9..b5623be0e731 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -5110,6 +5110,29 @@ public final class ActiveServices { return didSomething; } + void makeServicesNonForegroundLocked(final String pkg, final @UserIdInt int userId) { + final ServiceMap smap = mServiceMap.get(userId); + if (smap != null) { + ArrayList<ServiceRecord> fgsList = new ArrayList<>(); + for (int i = 0; i < smap.mServicesByInstanceName.size(); i++) { + final ServiceRecord sr = smap.mServicesByInstanceName.valueAt(i); + if (sr.appInfo.packageName.equals(pkg) && sr.isForeground) { + fgsList.add(sr); + } + } + + final int numServices = fgsList.size(); + if (DEBUG_FOREGROUND_SERVICE) { + Slog.i(TAG_SERVICE, "Forcing " + numServices + " services out of foreground in u" + + userId + "/" + pkg); + } + for (int i = 0; i < numServices; i++) { + final ServiceRecord sr = fgsList.get(i); + setServiceForegroundInnerLocked(sr, 0, null, Service.STOP_FOREGROUND_REMOVE, 0); + } + } + } + void forceStopPackageLocked(String packageName, int userId) { ServiceMap smap = mServiceMap.get(userId); if (smap != null && smap.mActiveForegroundApps.size() > 0) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index f6c110655e51..30745985951a 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3751,6 +3751,29 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override + public void makeServicesNonForeground(final String packageName, int userId) { + if (checkCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) + != PackageManager.PERMISSION_GRANTED) { + String msg = "Permission Denial: makeServicesNonForeground() from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid() + + " requires " + android.Manifest.permission.MANAGE_ACTIVITY_TASKS; + Slog.w(TAG, msg); + throw new SecurityException(msg); + } + + final int callingPid = Binder.getCallingPid(); + userId = mUserController.handleIncomingUser(callingPid, Binder.getCallingUid(), + userId, true, ALLOW_FULL_ONLY, "makeServicesNonForeground", null); + final long callingId = Binder.clearCallingIdentity(); + try { + makeServicesNonForegroundUnchecked(packageName, userId); + } finally { + Binder.restoreCallingIdentity(callingId); + } + } + + @Override public void forceStopPackage(final String packageName, int userId) { if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) != PackageManager.PERMISSION_GRANTED) { @@ -4058,6 +4081,13 @@ public class ActivityManagerService extends IActivityManager.Stub } } + private void makeServicesNonForegroundUnchecked(final String packageName, + final @UserIdInt int userId) { + synchronized (this) { + mServices.makeServicesNonForegroundLocked(packageName, userId); + } + } + @GuardedBy("this") private void forceStopPackageLocked(final String packageName, int uid, String reason) { forceStopPackageLocked(packageName, UserHandle.getAppId(uid), false, @@ -16399,6 +16429,11 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override + public void makeServicesNonForeground(String pkg, int userId) { + ActivityManagerService.this.makeServicesNonForegroundUnchecked(pkg, userId); + } + + @Override public void stopForegroundServicesForChannel(String pkg, int userId, String channelId) { synchronized (ActivityManagerService.this) { diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 685d606f8d41..0f7163987b2c 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -229,6 +229,8 @@ final class ActivityManagerShellCommand extends ShellCommand { return runBugReport(pw); case "force-stop": return runForceStop(pw); + case "stop-fgs": + return runStopForegroundServices(pw); case "fgs-notification-rate-limit": return runFgsNotificationRateLimit(pw); case "crash": @@ -1105,6 +1107,22 @@ final class ActivityManagerShellCommand extends ShellCommand { return 0; } + int runStopForegroundServices(PrintWriter pw) throws RemoteException { + int userId = UserHandle.USER_SYSTEM; + + String opt; + while ((opt = getNextOption()) != null) { + if (opt.equals("--user")) { + userId = UserHandle.parseUserArg(getNextArgRequired()); + } else { + getErrPrintWriter().println("Error: Unknown option: " + opt); + return -1; + } + } + mInterface.makeServicesNonForeground(getNextArgRequired(), userId); + return 0; + } + int runFgsNotificationRateLimit(PrintWriter pw) throws RemoteException { final String toggleValue = getNextArgRequired(); final boolean enable; |