summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java17
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java72
2 files changed, 64 insertions, 25 deletions
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index df92106ae0d0..90266f12a5dd 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -634,28 +634,13 @@ public final class ActiveServices {
}
if (allowBackgroundActivityStarts) {
- r.setHasStartedWhitelistingBgActivityStarts(true);
- scheduleCleanUpHasStartedWhitelistingBgActivityStartsLocked(r);
+ r.whitelistBgActivityStartsOnServiceStart();
}
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
- private void scheduleCleanUpHasStartedWhitelistingBgActivityStartsLocked(ServiceRecord r) {
- // if there's a request pending from the past, drop it before scheduling a new one
- if (r.startedWhitelistingBgActivityStartsCleanUp == null) {
- r.startedWhitelistingBgActivityStartsCleanUp = () -> {
- synchronized(mAm) {
- r.setHasStartedWhitelistingBgActivityStarts(false);
- }
- };
- }
- mAm.mHandler.removeCallbacks(r.startedWhitelistingBgActivityStartsCleanUp);
- mAm.mHandler.postDelayed(r.startedWhitelistingBgActivityStartsCleanUp,
- mAm.mConstants.SERVICE_BG_ACTIVITY_START_TIMEOUT);
- }
-
private boolean requestStartTargetPermissionsReviewIfNeededLocked(ServiceRecord r,
String callingPackage, int callingUid, Intent service, boolean callerFg,
final int userId) {
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 0426ec1d9771..2f1b22ec9a67 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -135,7 +135,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
// allowBackgroundActivityStarts=true to startServiceLocked()?
private boolean mHasStartedWhitelistingBgActivityStarts;
// used to clean up the state of hasStartedWhitelistingBgActivityStarts after a timeout
- Runnable startedWhitelistingBgActivityStartsCleanUp;
+ private Runnable mStartedWhitelistingBgActivityStartsCleanUp;
+ private ProcessRecord mAppForStartedWhitelistingBgActivityStarts;
String stringName; // caching of toString
@@ -541,14 +542,35 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
public void setProcess(ProcessRecord _proc) {
if (_proc != null) {
+ // We're starting a new process for this service, but a previous one is whitelisted.
+ // Remove that whitelisting now (unless the new process is the same as the previous one,
+ // which is a common case).
+ if (mAppForStartedWhitelistingBgActivityStarts != null) {
+ if (mAppForStartedWhitelistingBgActivityStarts != _proc) {
+ mAppForStartedWhitelistingBgActivityStarts
+ .removeAllowBackgroundActivityStartsToken(this);
+ ams.mHandler.removeCallbacks(mStartedWhitelistingBgActivityStartsCleanUp);
+ }
+ mAppForStartedWhitelistingBgActivityStarts = null;
+ }
+ if (mHasStartedWhitelistingBgActivityStarts) {
+ // Make sure the cleanup callback knows about the new process.
+ mAppForStartedWhitelistingBgActivityStarts = _proc;
+ }
if (mHasStartedWhitelistingBgActivityStarts
|| mHasBindingWhitelistingBgActivityStarts) {
_proc.addAllowBackgroundActivityStartsToken(this);
} else {
_proc.removeAllowBackgroundActivityStartsToken(this);
}
- } else if (app != null) {
- app.removeAllowBackgroundActivityStartsToken(this);
+ }
+ if (app != null && app != _proc) {
+ // If the old app is whitelisted because of a service start, leave it whitelisted until
+ // the cleanup callback runs. Otherwise we can remove it from the whitelist immediately
+ // (it can't be bound now).
+ if (!mHasStartedWhitelistingBgActivityStarts) {
+ app.removeAllowBackgroundActivityStartsToken(this);
+ }
app.updateBoundClientUids();
}
app = _proc;
@@ -616,10 +638,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
break;
}
}
- if (mHasBindingWhitelistingBgActivityStarts != hasWhitelistingBinding) {
- mHasBindingWhitelistingBgActivityStarts = hasWhitelistingBinding;
- updateParentProcessBgActivityStartsWhitelistingToken();
- }
+ setHasBindingWhitelistingBgActivityStarts(hasWhitelistingBinding);
}
void setHasBindingWhitelistingBgActivityStarts(boolean newValue) {
@@ -629,7 +648,42 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
}
}
- void setHasStartedWhitelistingBgActivityStarts(boolean newValue) {
+ /**
+ * Called when the service is started with allowBackgroundActivityStarts set. We whitelist
+ * it for background activity starts, setting up a callback to remove the whitelisting after a
+ * timeout. Note that the whitelisting persists for the process even if the service is
+ * subsequently stopped.
+ */
+ void whitelistBgActivityStartsOnServiceStart() {
+ setHasStartedWhitelistingBgActivityStarts(true);
+
+ // This callback is stateless, so we create it once when we first need it.
+ if (mStartedWhitelistingBgActivityStartsCleanUp == null) {
+ mStartedWhitelistingBgActivityStartsCleanUp = () -> {
+ synchronized (ams) {
+ if (app == mAppForStartedWhitelistingBgActivityStarts) {
+ // The process we whitelisted is still running the service. We remove
+ // the started whitelisting, but it may still be whitelisted via bound
+ // connections.
+ setHasStartedWhitelistingBgActivityStarts(false);
+ } else if (mAppForStartedWhitelistingBgActivityStarts != null) {
+ // The process we whitelisted is not running the service. It therefore
+ // can't be bound so we can unconditionally remove the whitelist.
+ mAppForStartedWhitelistingBgActivityStarts
+ .removeAllowBackgroundActivityStartsToken(ServiceRecord.this);
+ }
+ mAppForStartedWhitelistingBgActivityStarts = null;
+ }
+ };
+ }
+
+ // if there's a request pending from the past, drop it before scheduling a new one
+ ams.mHandler.removeCallbacks(mStartedWhitelistingBgActivityStartsCleanUp);
+ ams.mHandler.postDelayed(mStartedWhitelistingBgActivityStartsCleanUp,
+ ams.mConstants.SERVICE_BG_ACTIVITY_START_TIMEOUT);
+ }
+
+ private void setHasStartedWhitelistingBgActivityStarts(boolean newValue) {
if (mHasStartedWhitelistingBgActivityStarts != newValue) {
mHasStartedWhitelistingBgActivityStarts = newValue;
updateParentProcessBgActivityStartsWhitelistingToken();
@@ -650,7 +704,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
return;
}
if (mHasStartedWhitelistingBgActivityStarts || mHasBindingWhitelistingBgActivityStarts) {
- // if the token is already there it's safe to "re-add it" - we're deadling with
+ // if the token is already there it's safe to "re-add it" - we're dealing with
// a set of Binder objects
app.addAllowBackgroundActivityStartsToken(this);
} else {