diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 3b3febea0272e..89781d3fbb0a5 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -1976,7 +1976,7 @@ public final class ActiveServices { r.foregroundId = 0; r.foregroundNoti = null; } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) { - r.stripForegroundServiceFlagFromNotification(); + dropFgsNotificationStateLocked(r); if ((flags & Service.STOP_FOREGROUND_DETACH) != 0) { r.foregroundId = 0; r.foregroundNoti = null; @@ -4225,9 +4225,10 @@ public final class ActiveServices { } r.isForeground = false; + r.mFgsNotificationWasDeferred = false; + dropFgsNotificationStateLocked(r); r.foregroundId = 0; r.foregroundNoti = null; - r.mFgsNotificationWasDeferred = false; resetFgsRestrictionLocked(r); // Clear start entries. @@ -4291,6 +4292,35 @@ public final class ActiveServices { smap.ensureNotStartingBackgroundLocked(r); } + private void dropFgsNotificationStateLocked(ServiceRecord r) { + // If this is the only FGS using this notification, clear its FGS flag + boolean shared = false; + final ServiceMap smap = mServiceMap.get(r.userId); + if (smap != null) { + // Is any other FGS using this notification? + final int numServices = smap.mServicesByInstanceName.size(); + for (int i = 0; i < numServices; i++) { + final ServiceRecord sr = smap.mServicesByInstanceName.valueAt(i); + if (sr == r) { + continue; + } + if (sr.isForeground + && r.foregroundId == sr.foregroundId + && r.appInfo.packageName.equals(sr.appInfo.packageName)) { + shared = true; + break; + } + } + } else { + Slog.wtf(TAG, "FGS " + r + " not found!"); + } + + // No other FGS is sharing this notification, so we're done with it + if (!shared) { + r.stripForegroundServiceFlagFromNotification(); + } + } + void removeConnectionLocked(ConnectionRecord c, ProcessRecord skipApp, ActivityServiceConnectionsHolder skipAct, boolean enqueueOomAdj) { IBinder binder = c.conn.asBinder(); diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index 141f081ab9a7a..804e442bc8dea 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -20,6 +20,7 @@ import static android.app.PendingIntent.FLAG_IMMUTABLE; import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; import static android.os.PowerExemptionManager.REASON_DENIED; +import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOREGROUND_SERVICE; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -928,13 +929,17 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN public void postNotification() { final int appUid = appInfo.uid; final int appPid = app.getPid(); - if (foregroundId != 0 && foregroundNoti != null) { + if (isForeground && foregroundNoti != null) { // Do asynchronous communication with notification manager to // avoid deadlocks. final String localPackageName = packageName; final int localForegroundId = foregroundId; final Notification _foregroundNoti = foregroundNoti; final ServiceRecord record = this; + if (DEBUG_FOREGROUND_SERVICE) { + Slog.d(TAG, "Posting notification " + _foregroundNoti + + " for foreground service " + this); + } ams.mHandler.post(new Runnable() { public void run() { NotificationManagerInternal nm = LocalServices.getService( @@ -1066,10 +1071,6 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN } public void stripForegroundServiceFlagFromNotification() { - if (foregroundId == 0) { - return; - } - final int localForegroundId = foregroundId; final int localUserId = userId; final String localPackageName = packageName;