Improve test flakiness around FGS notifications
Make sure that even transient package-associated state is cleared when the package is uninstalled, and provide a testing hook for instrumenting global rate limits appropriately to high-rate test sequences. Bug: 190019349 Test: atest CtsAppTestCases:android.app.cts.ServiceTest Test: atest CtsAppTestCases:android.app.cts.NotificationManagerTest Change-Id: Ic38157c6f21bcf09bcf74de591e41dc64f7bf0f7
This commit is contained in:
@@ -685,6 +685,14 @@ interface IActivityManager {
|
||||
*/
|
||||
boolean enableAppFreezer(in boolean enable);
|
||||
|
||||
/**
|
||||
* Suppress or reenable the rate limit on foreground service notification deferral.
|
||||
* This is for use within CTS and is protected by android.permission.WRITE_DEVICE_CONFIG.
|
||||
*
|
||||
* @param enable false to suppress rate-limit policy; true to reenable it.
|
||||
*/
|
||||
boolean enableFgsNotificationRateLimit(in boolean enable);
|
||||
|
||||
/**
|
||||
* Holds the AM lock for the specified amount of milliseconds.
|
||||
* This is intended for use by the tests that need to imitate lock contention.
|
||||
|
||||
@@ -249,6 +249,14 @@ public final class ActiveServices {
|
||||
*/
|
||||
final ArrayList<ServiceRecord> mPendingFgsNotifications = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Whether there is a rate limit that suppresses immediate re-deferral of new FGS
|
||||
* notifications from each app. On by default, disabled only by shell command for
|
||||
* test-suite purposes. To disable the behavior more generally, use the usual
|
||||
* DeviceConfig mechanism to set the rate limit interval to zero.
|
||||
*/
|
||||
private boolean mFgsDeferralRateLimited = true;
|
||||
|
||||
/**
|
||||
* Uptime at which a given uid becomes eliglible again for FGS notification deferral
|
||||
*/
|
||||
@@ -2142,8 +2150,10 @@ public final class ActiveServices {
|
||||
}
|
||||
}
|
||||
|
||||
final long nextEligible = when + mAm.mConstants.mFgsNotificationDeferralExclusionTime;
|
||||
mFgsDeferralEligible.put(uid, nextEligible);
|
||||
if (mFgsDeferralRateLimited) {
|
||||
final long nextEligible = when + mAm.mConstants.mFgsNotificationDeferralExclusionTime;
|
||||
mFgsDeferralEligible.put(uid, nextEligible);
|
||||
}
|
||||
r.fgDisplayTime = when;
|
||||
r.mFgsNotificationDeferred = true;
|
||||
r.mFgsNotificationShown = false;
|
||||
@@ -2204,6 +2214,38 @@ public final class ActiveServices {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Suppress or reenable the rate limit on foreground service notification deferral.
|
||||
* Invoked from the activity manager shell command.
|
||||
*
|
||||
* @param enable false to suppress rate-limit policy; true to reenable it.
|
||||
*/
|
||||
boolean enableFgsNotificationRateLimitLocked(final boolean enable) {
|
||||
if (enable != mFgsDeferralRateLimited) {
|
||||
mFgsDeferralRateLimited = enable;
|
||||
if (!enable) {
|
||||
// make sure to reset any active rate limiting
|
||||
mFgsDeferralEligible.clear();
|
||||
}
|
||||
}
|
||||
return enable;
|
||||
}
|
||||
|
||||
private void removeServiceNotificationDeferralsLocked(String packageName,
|
||||
final @UserIdInt int userId) {
|
||||
for (int i = mPendingFgsNotifications.size() - 1; i >= 0; i--) {
|
||||
final ServiceRecord r = mPendingFgsNotifications.get(i);
|
||||
if (userId == r.userId
|
||||
&& r.appInfo.packageName.equals(packageName)) {
|
||||
mPendingFgsNotifications.remove(i);
|
||||
if (DEBUG_FOREGROUND_SERVICE) {
|
||||
Slog.d(TAG_SERVICE, "Removing notification deferral for "
|
||||
+ r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeLogFGSStateEnteredLocked(ServiceRecord r) {
|
||||
if (r.mLogEntering) {
|
||||
logFGSStateChangeLocked(r,
|
||||
@@ -4690,6 +4732,7 @@ public final class ActiveServices {
|
||||
}
|
||||
}
|
||||
removeServiceRestartBackoffEnabledLocked(packageName);
|
||||
removeServiceNotificationDeferralsLocked(packageName, userId);
|
||||
}
|
||||
|
||||
void cleanUpServices(int userId, ComponentName component, Intent baseIntent) {
|
||||
|
||||
@@ -17065,6 +17065,19 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Suppress or reenable the rate limit on foreground service notification deferral.
|
||||
* @param enable false to suppress rate-limit policy; true to reenable it.
|
||||
*/
|
||||
@Override
|
||||
public boolean enableFgsNotificationRateLimit(boolean enable) {
|
||||
enforceCallingPermission(permission.WRITE_DEVICE_CONFIG,
|
||||
"enableFgsNotificationRateLimit");
|
||||
synchronized (this) {
|
||||
return mServices.enableFgsNotificationRateLimitLocked(enable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds the AM lock for the specified amount of milliseconds.
|
||||
* Intended for use by the tests that need to imitate lock contention.
|
||||
|
||||
@@ -230,6 +230,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
return runBugReport(pw);
|
||||
case "force-stop":
|
||||
return runForceStop(pw);
|
||||
case "fgs-notification-rate-limit":
|
||||
return runFgsNotificationRateLimit(pw);
|
||||
case "crash":
|
||||
return runCrash(pw);
|
||||
case "kill":
|
||||
@@ -1103,6 +1105,24 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int runFgsNotificationRateLimit(PrintWriter pw) throws RemoteException {
|
||||
final String toggleValue = getNextArgRequired();
|
||||
final boolean enable;
|
||||
switch (toggleValue) {
|
||||
case "enable":
|
||||
enable = true;
|
||||
break;
|
||||
case "disable":
|
||||
enable = false;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Argument must be either 'enable' or 'disable'");
|
||||
}
|
||||
mInterface.enableFgsNotificationRateLimit(enable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int runCrash(PrintWriter pw) throws RemoteException {
|
||||
int userId = UserHandle.USER_ALL;
|
||||
|
||||
@@ -3303,6 +3323,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
pw.println(" when done to select where it should be delivered. Options are:");
|
||||
pw.println(" --progress: will launch a notification right away to show its progress.");
|
||||
pw.println(" --telephony: will dump only telephony sections.");
|
||||
pw.println(" fgs-notification-rate-limit {enable | disable}");
|
||||
pw.println(" Enable/disable rate limit on FGS notification deferral policy.");
|
||||
pw.println(" force-stop [--user <USER_ID> | all | current] <PACKAGE>");
|
||||
pw.println(" Completely stop the given application package.");
|
||||
pw.println(" crash [--user <USER_ID>] <PACKAGE|PID>");
|
||||
|
||||
Reference in New Issue
Block a user