Properly reset FGS notification associations
When the service is brought down, the notification needs to be properly freed from FGS-related policy. When the same notification is being shared by multiple live FGS instances, it needs to remain flagged until the last of them exits that state. Along the way, fix a latent bug that resulted in incorrect notification behavior when an FGS's associated notification had id 0. Bug: 191518901 Test: CtsAppTestCases:android.app.cts.ServiceTest Change-Id: If8bae1c04d98cbab848823c86951544f792efba4
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user