Implement demotion of an app's FGses
The OS now has an operation for wholesale shutting down all of an application's foreground services. Bug: 192504071 Test: atest CtsAppTestCases:android.app.cts.ServiceTest Test: ApiDemos + shell command Change-Id: I67d4469d5c20c25c717024fad80849c080c98190
This commit is contained in:
@@ -517,6 +517,11 @@ public abstract class ActivityManagerInternal {
|
||||
public abstract void onForegroundServiceNotificationUpdate(boolean shown,
|
||||
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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -3750,6 +3750,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)
|
||||
@@ -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,
|
||||
@@ -16398,6 +16428,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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user