Merge "Work on issue #11634365: Leaking restarting services" into klp-dev
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 804cd0d..a80afbc 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -307,7 +307,7 @@
ServiceRecord r = res.record;
NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
callingUid, r.packageName, service, service.getFlags(), null);
- if (unscheduleServiceRestartLocked(r, callingUid)) {
+ if (unscheduleServiceRestartLocked(r, callingUid, false)) {
if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
}
r.lastActivity = SystemClock.uptimeMillis();
@@ -701,7 +701,7 @@
final long origId = Binder.clearCallingIdentity();
try {
- if (unscheduleServiceRestartLocked(s, callerApp.info.uid)) {
+ if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {
if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
+ s);
}
@@ -1002,14 +1002,11 @@
smap.mServicesByIntent.put(filter, r);
// Make sure this component isn't in the pending list.
- int N = mPendingServices.size();
- for (int i=0; i<N; i++) {
+ for (int i=mPendingServices.size()-1; i>=0; i--) {
ServiceRecord pr = mPendingServices.get(i);
if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
&& pr.name.equals(name)) {
mPendingServices.remove(i);
- i--;
- N--;
}
}
}
@@ -1101,6 +1098,14 @@
boolean allowCancel) {
boolean canceled = false;
+ ServiceMap smap = getServiceMap(r.userId);
+ if (smap.mServicesByName.get(r.name) != r) {
+ ServiceRecord cur = smap.mServicesByName.get(r.name);
+ Slog.wtf(TAG, "Attempting to schedule restart of " + r
+ + " when found in map: " + cur);
+ return false;
+ }
+
final long now = SystemClock.uptimeMillis();
if ((r.serviceInfo.applicationInfo.flags
@@ -1210,8 +1215,9 @@
bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true);
}
- private final boolean unscheduleServiceRestartLocked(ServiceRecord r, int callingUid) {
- if (r.restartDelay == 0) {
+ private final boolean unscheduleServiceRestartLocked(ServiceRecord r, int callingUid,
+ boolean force) {
+ if (!force && r.restartDelay == 0) {
return false;
}
// Remove from the restarting list; if the service is currently on the
@@ -1222,12 +1228,31 @@
r.resetRestartCounter();
}
if (removed) {
- r.clearRestarting(mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis());
+ clearRestartingIfNeededLocked(r);
}
mAm.mHandler.removeCallbacks(r.restarter);
return true;
}
+ private void clearRestartingIfNeededLocked(ServiceRecord r) {
+ if (r.restartTracker != null) {
+ // If this is the last restarting record with this tracker, then clear
+ // the tracker's restarting state.
+ boolean stillTracking = false;
+ for (int i=mRestartingServices.size()-1; i>=0; i--) {
+ if (mRestartingServices.get(i).restartTracker == r.restartTracker) {
+ stillTracking = true;
+ break;
+ }
+ }
+ if (!stillTracking) {
+ r.restartTracker.setRestarting(false, mAm.mProcessStats.getMemFactorLocked(),
+ SystemClock.uptimeMillis());
+ r.restartTracker = null;
+ }
+ }
+ }
+
private final String bringUpServiceLocked(ServiceRecord r,
int intentFlags, boolean execInFg, boolean whileRestarting) {
//Slog.i(TAG, "Bring up service:");
@@ -1248,7 +1273,7 @@
// We are now bringing the service up, so no longer in the
// restarting state.
if (mRestartingServices.remove(r)) {
- r.clearRestarting(mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis());
+ clearRestartingIfNeededLocked(r);
}
// Make sure this service is no longer considered delayed, we are starting it now.
@@ -1560,16 +1585,13 @@
smap.mServicesByName.remove(r.name);
smap.mServicesByIntent.remove(r.intent);
r.totalRestartCount = 0;
- unscheduleServiceRestartLocked(r, 0);
+ unscheduleServiceRestartLocked(r, 0, true);
// Also make sure it is not on the pending list.
- int N = mPendingServices.size();
- for (int i=0; i<N; i++) {
+ for (int i=mPendingServices.size()-1; i>=0; i--) {
if (mPendingServices.get(i) == r) {
mPendingServices.remove(i);
if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
- i--;
- N--;
}
}
@@ -2076,8 +2098,14 @@
if (r.processName.equals(app.processName) &&
r.serviceInfo.applicationInfo.uid == app.info.uid) {
mRestartingServices.remove(i);
- r.clearRestarting(mAm.mProcessStats.getMemFactorLocked(),
- SystemClock.uptimeMillis());
+ clearRestartingIfNeededLocked(r);
+ }
+ }
+ for (int i=mPendingServices.size()-1; i>=0; i--) {
+ ServiceRecord r = mPendingServices.get(i);
+ if (r.processName.equals(app.processName) &&
+ r.serviceInfo.applicationInfo.uid == app.info.uid) {
+ mPendingServices.remove(i);
}
}
}
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 84b1c3a..80e6e94 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -354,13 +354,6 @@
restartTracker.setRestarting(true, memFactor, now);
}
- public void clearRestarting(int memFactor, long now) {
- if (restartTracker != null) {
- restartTracker.setRestarting(false, memFactor, now);
- restartTracker = null;
- }
- }
-
public AppBindRecord retrieveAppBindingLocked(Intent intent,
ProcessRecord app) {
Intent.FilterComparison filter = new Intent.FilterComparison(intent);