Merge "Make service start whitelisting for background activity starts persist after service start." into qt-dev
am: 7b0194c461
Change-Id: I79f053410254d6571c6b9e7278ae5f65a947f1a5
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index df92106..90266f1 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 @@
}
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 0426ec1..2f1b22e 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 @@
// 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 @@
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 @@
break;
}
}
- if (mHasBindingWhitelistingBgActivityStarts != hasWhitelistingBinding) {
- mHasBindingWhitelistingBgActivityStarts = hasWhitelistingBinding;
- updateParentProcessBgActivityStartsWhitelistingToken();
- }
+ setHasBindingWhitelistingBgActivityStarts(hasWhitelistingBinding);
}
void setHasBindingWhitelistingBgActivityStarts(boolean newValue) {
@@ -629,7 +648,42 @@
}
}
- 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 @@
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 {