From 075de7ea1daae7a0c6a3e979970569d822de9dbb Mon Sep 17 00:00:00 2001 From: Christopher Tate Date: Wed, 14 Jul 2021 14:18:38 -0700 Subject: [PATCH] Ensure notification visibility on stopForeground(false) If an FGS notification has been deferred but the app needs it to remain present after the service exits the FGS mode, make sure that it gets shown. Bug: 193665032 Test: atest CtsAppTestCases:android.app.cts.ServiceTest#testForegroundService_deferThenKeepNotification Change-Id: I1e9c5f1b27dd670639bd5e02b7f79839cfb5362e --- .../com/android/server/am/ActiveServices.java | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index b5ead200cea56..15042f6f017ab 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -1934,6 +1934,28 @@ public final class ActiveServices { if (smap != null) { decActiveForegroundAppLocked(smap, r); } + + // Adjust notification handling before setting isForeground to false, because + // that state is relevant to the notification policy side. + // Leave the time-to-display as already set: re-entering foreground mode will + // only resume the previous quiet timeout, or will display immediately if the + // deferral period had already passed. + if ((flags & Service.STOP_FOREGROUND_REMOVE) != 0) { + cancelForegroundNotificationLocked(r); + r.foregroundId = 0; + r.foregroundNoti = null; + } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) { + // if it's been deferred, force to visibility + if (!r.mFgsNotificationShown) { + r.postNotification(); + } + dropFgsNotificationStateLocked(r); + if ((flags & Service.STOP_FOREGROUND_DETACH) != 0) { + r.foregroundId = 0; + r.foregroundNoti = null; + } + } + r.isForeground = false; r.mFgsExitTime = SystemClock.uptimeMillis(); ServiceState stracker = r.getTracker(); @@ -1957,20 +1979,6 @@ public final class ActiveServices { updateServiceForegroundLocked(r.app.mServices, true); } } - // Leave the time-to-display as already set: re-entering foreground mode will - // only resume the previous quiet timeout, or will display immediately if the - // deferral period had already passed. - if ((flags & Service.STOP_FOREGROUND_REMOVE) != 0) { - cancelForegroundNotificationLocked(r); - r.foregroundId = 0; - r.foregroundNoti = null; - } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) { - dropFgsNotificationStateLocked(r); - if ((flags & Service.STOP_FOREGROUND_DETACH) != 0) { - r.foregroundId = 0; - r.foregroundNoti = null; - } - } } }