Fix issue #29506774: Foreground Service Can Avoid Notification Requirement

Don't cancel the notification if there are other foreground
services using the same notification ID.

Change-Id: I02a49d9a07af0203e59e70be2dc6773f3cefee47
This commit is contained in:
Dianne Hackborn
2016-08-01 17:49:41 -07:00
parent fea7cfce8b
commit 0ba4c710c6
2 changed files with 43 additions and 24 deletions

View File

@@ -699,7 +699,7 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
}
}
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 @@ public final class ActiveServices {
}
}
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
}
}
r.cancelNotification();
cancelForegroudNotificationLocked(r);
r.isForeground = false;
r.foregroundId = 0;
r.foregroundNoti = null;

View File

@@ -543,27 +543,25 @@ final class ServiceRecord extends Binder {
}
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() {