Fix issue #29506774: Foreground Service Can Avoid Notification Requirement am: 0ba4c710c6
am: e1315924f1
Change-Id: I67d77792716287073352cb9f50a7f192f8f3fc90
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index ee2fa51..a3d2ebb 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -699,7 +699,7 @@
throw new IllegalArgumentException("null notification");
}
if (r.foregroundId != id) {
- r.cancelNotification();
+ cancelForegroudNotificationLocked(r);
r.foregroundId = id;
}
notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
@@ -721,7 +721,7 @@
}
}
if ((flags & Service.STOP_FOREGROUND_REMOVE) != 0) {
- r.cancelNotification();
+ cancelForegroudNotificationLocked(r);
r.foregroundId = 0;
r.foregroundNoti = null;
} else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
@@ -738,6 +738,27 @@
}
}
+ private void cancelForegroudNotificationLocked(ServiceRecord r) {
+ if (r.foregroundId != 0) {
+ // First check to see if this app has any other active foreground services
+ // with the same notification ID. If so, we shouldn't actually cancel it,
+ // because that would wipe away the notification that still needs to be shown
+ // due the other service.
+ ServiceMap sm = getServiceMap(r.userId);
+ if (sm != null) {
+ for (int i = sm.mServicesByName.size()-1; i >= 0; i--) {
+ ServiceRecord other = sm.mServicesByName.valueAt(i);
+ if (other.foregroundId == r.foregroundId
+ && other.packageName.equals(r.packageName)) {
+ // Found one! Abort the cancel.
+ return;
+ }
+ }
+ }
+ r.cancelNotification();
+ }
+ }
+
private void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
boolean anyForeground = false;
for (int i=proc.services.size()-1; i>=0; i--) {
@@ -1560,7 +1581,7 @@
r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(), now);
}
- r.cancelNotification();
+ cancelForegroudNotificationLocked(r);
mAm.mHandler.removeCallbacks(r.restarter);
mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime);
@@ -2022,7 +2043,7 @@
}
}
- r.cancelNotification();
+ cancelForegroudNotificationLocked(r);
r.isForeground = false;
r.foregroundId = 0;
r.foregroundNoti = null;
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 2bfc402..71c7fd3 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -543,27 +543,25 @@
}
public void cancelNotification() {
- if (foregroundId != 0) {
- // Do asynchronous communication with notification manager to
- // avoid deadlocks.
- final String localPackageName = packageName;
- final int localForegroundId = foregroundId;
- ams.mHandler.post(new Runnable() {
- public void run() {
- INotificationManager inm = NotificationManager.getService();
- if (inm == null) {
- return;
- }
- try {
- inm.cancelNotificationWithTag(localPackageName, null,
- localForegroundId, userId);
- } catch (RuntimeException e) {
- Slog.w(TAG, "Error canceling notification for service", e);
- } catch (RemoteException e) {
- }
+ // Do asynchronous communication with notification manager to
+ // avoid deadlocks.
+ final String localPackageName = packageName;
+ final int localForegroundId = foregroundId;
+ ams.mHandler.post(new Runnable() {
+ public void run() {
+ INotificationManager inm = NotificationManager.getService();
+ if (inm == null) {
+ return;
}
- });
- }
+ try {
+ inm.cancelNotificationWithTag(localPackageName, null,
+ localForegroundId, userId);
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Error canceling notification for service", e);
+ } catch (RemoteException e) {
+ }
+ }
+ });
}
public void stripForegroundServiceFlagFromNotification() {