summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Michal Karpinski <mkarpinski@google.com> 2019-03-07 16:15:14 +0000
committer Michal Karpinski <mkarpinski@google.com> 2019-03-13 11:29:12 +0000
commite069b0022f5aa090d00b9266f2760cb2c7a6e97f (patch)
tree40fd05629bec7e065c44ed89e56258343481f590
parent794d22d0a7a02ada66e526bd56eac1170977eedb (diff)
Add new BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS binding flag
and the mechanism to use it Since both starts and bindings might be contributing to the service being whitelisted, track the state in ServiceRecord and update the parent process accordingly when changes happen. While we're at it, add that flag for bindings to accessibility services, voice interaction services and QSTiles. Also, make the timeout constant configurable for start-based whitelisting. Bug: 124298522 Bug: 123495976 (accessibility services) Bug: 123337181 (paying via NFC, like Google Pay) Bug: 122887611 (binding to InCallService) Bug: 127774234 (binding to QSTile) Bug: 124288681 (binding to voice interaction services) Test: atest WmTests:ActivityStarterTests Test: atest AccessibilityServiceConnectionTest Test: manual with: 1) notifications from calendar and dynamite to test service starts whitelisting 2) enabling talkback and livetranscribe to test service bindings whitelisting 3) adding the LastPass QSTile and clicking on it Change-Id: I8b6f23f999683920411ca40ab5b25c688a4f7055
-rw-r--r--core/java/android/content/Context.java9
-rw-r--r--core/java/android/provider/Settings.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java4
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java3
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java93
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerConstants.java10
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java81
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java4
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java3
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java6
10 files changed, 162 insertions, 52 deletions
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index f896274ed8b3..91ac9e0dcb01 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -338,6 +338,15 @@ public abstract class Context {
public static final int BIND_ADJUST_BELOW_PERCEPTIBLE = 0x0100;
/**
+ * Flag for {@link #bindService}: allow background activity starts from the bound service's
+ * process.
+ * This flag is only respected if the caller is holding
+ * {@link android.Manifest.permission#START_ACTIVITIES_FROM_BACKGROUND}.
+ * @hide
+ */
+ public static final int BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS = 0x00100000;
+
+ /**
* @hide Flag for {@link #bindService}: the service being bound to represents a
* protected system component, so must have association restrictions applied to it.
* That is, a system config must have one or more allow-association tags limiting
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4836e6c0cba7..e8f91ca04d63 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11508,6 +11508,7 @@ public final class Settings {
* service_min_restart_time_between (long)
* service_max_inactivity (long)
* service_bg_start_timeout (long)
+ * service_bg_activity_start_timeout (long)
* process_start_async (boolean)
* </pre>
*
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 305fbf2e3e98..b135f7b27c3f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -159,8 +159,8 @@ public class TileLifecycleManager extends BroadcastReceiver implements
mBindTryCount++;
try {
mIsBound = mContext.bindServiceAsUser(mIntent, this,
- Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
- mUser);
+ Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE
+ | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, mUser);
} catch (SecurityException e) {
Log.e(TAG, "Failed to bind to service", e);
mIsBound = false;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index a19a84724d45..3bd6220b4767 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -91,7 +91,8 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect
if (userState == null) return;
final long identity = Binder.clearCallingIdentity();
try {
- int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE;
+ int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE
+ | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS;
if (userState.getBindInstantServiceAllowed()) {
flags |= Context.BIND_ALLOW_INSTANT;
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 85ec2dd55e89..627010606b31 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -131,9 +131,6 @@ public final class ActiveServices {
// calling startForeground() before we ANR + stop it.
static final int SERVICE_START_FOREGROUND_TIMEOUT = 10*1000;
- // For how long after a whitelisted service's start its process can start a background activity
- private static final int SERVICE_BG_ACTIVITY_START_TIMEOUT_MS = 10*1000;
-
final ActivityManagerService mAm;
// Maximum number of services that we allow to start in the background
@@ -333,8 +330,8 @@ public final class ActiveServices {
+ " delayedStop=" + r.delayedStop);
} else {
try {
- startServiceInnerLocked(this, r.pendingStarts.get(0).intent, r, false, true,
- false);
+ startServiceInnerLocked(this, r.pendingStarts.get(0).intent, r, false,
+ true);
} catch (TransactionTooLargeException e) {
// Ignore, nobody upstack cares.
}
@@ -637,26 +634,26 @@ public final class ActiveServices {
}
if (allowBackgroundActivityStarts) {
- ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
- if (proc != null) {
- proc.addAllowBackgroundActivityStartsToken(r);
- // schedule removal of the whitelisting token after the timeout
- removeAllowBackgroundActivityStartsServiceToken(proc, r,
- SERVICE_BG_ACTIVITY_START_TIMEOUT_MS);
- }
+ r.hasStartedWhitelistingBgActivityStarts = true;
+ scheduleCleanUpHasStartedWhitelistingBgActivityStartsLocked(r);
}
- ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting,
- allowBackgroundActivityStarts);
+
+ ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
- private void removeAllowBackgroundActivityStartsServiceToken(ProcessRecord proc,
- ServiceRecord r, int delayMillis) {
- mAm.mHandler.postDelayed(() -> {
- if (proc != null) {
- proc.removeAllowBackgroundActivityStartsToken(r);
- }
- }, delayMillis);
+ 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,
@@ -705,8 +702,7 @@ public final class ActiveServices {
}
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
- boolean callerFg, boolean addToStarting, boolean allowBackgroundActivityStarts)
- throws TransactionTooLargeException {
+ boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
ServiceState stracker = r.getTracker();
if (stracker != null) {
stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
@@ -717,8 +713,7 @@ public final class ActiveServices {
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
}
- String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false,
- allowBackgroundActivityStarts);
+ String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
if (error != null) {
return new ComponentName("!!", error);
}
@@ -765,6 +760,12 @@ public final class ActiveServices {
SystemClock.uptimeMillis());
}
service.callStart = false;
+
+ // the service will not necessarily be brought down, so only clear the whitelisting state
+ // for start-based bg activity starts now, and drop any existing future cleanup callback
+ service.setHasStartedWhitelistingBgActivityStarts(false);
+ mAm.mHandler.removeCallbacks(service.startedWhitelistingBgActivityStartsCleanUp);
+
bringDownServiceIfNeededLocked(service, false, false);
}
@@ -788,9 +789,6 @@ public final class ActiveServices {
if (r.record != null) {
final long origId = Binder.clearCallingIdentity();
try {
- // immediately remove bg activity whitelisting token if there was one
- removeAllowBackgroundActivityStartsServiceToken(callerApp, r.record,
- 0 /* delayMillis */);
stopServiceLocked(r.record);
} finally {
Binder.restoreCallingIdentity(origId);
@@ -1614,6 +1612,12 @@ public final class ActiveServices {
+ ") set BIND_ALLOW_INSTANT when binding service " + service);
}
+ if ((flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) {
+ mAm.enforceCallingPermission(
+ android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
+ "BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS");
+ }
+
final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0;
@@ -1672,7 +1676,7 @@ public final class ActiveServices {
try {
bringUpServiceLocked(serviceRecord,
serviceIntent.getFlags(),
- callerFg, false, false, false);
+ callerFg, false, false);
} catch (RemoteException e) {
/* ignore - local call */
}
@@ -1762,6 +1766,9 @@ public final class ActiveServices {
if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
s.whitelistManager = true;
}
+ if ((flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) {
+ s.setHasBindingWhitelistingBgActivityStarts(true);
+ }
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
@@ -1775,7 +1782,7 @@ public final class ActiveServices {
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
- permissionsReviewRequired, false) != null) {
+ permissionsReviewRequired) != null) {
return 0;
}
}
@@ -2445,8 +2452,7 @@ public final class ActiveServices {
return;
}
try {
- bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false,
- false);
+ bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false);
} catch (TransactionTooLargeException e) {
// Ignore, it's been logged and nothing upstack cares.
}
@@ -2491,11 +2497,8 @@ public final class ActiveServices {
}
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
- boolean whileRestarting, boolean permissionsReviewRequired,
- boolean allowBackgroundActivityStarts) throws TransactionTooLargeException {
- //Slog.i(TAG, "Bring up service:");
- //r.dump(" ");
-
+ boolean whileRestarting, boolean permissionsReviewRequired)
+ throws TransactionTooLargeException {
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
@@ -2603,13 +2606,6 @@ public final class ActiveServices {
}
}
- if (app != null && allowBackgroundActivityStarts) {
- app.addAllowBackgroundActivityStartsToken(r);
- // schedule removal of the whitelisting token after the timeout
- removeAllowBackgroundActivityStartsServiceToken(app, r,
- SERVICE_BG_ACTIVITY_START_TIMEOUT_MS);
- }
-
if (r.fgRequired) {
if (DEBUG_FOREGROUND_SERVICE) {
Slog.v(TAG, "Whitelisting " + UserHandle.formatUid(r.appInfo.uid)
@@ -2646,6 +2642,11 @@ public final class ActiveServices {
}
}
+ /**
+ * Note the name of this method should not be confused with the started services concept.
+ * The "start" here means bring up the instance in the client, and this method is called
+ * from bindService() as well.
+ */
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
if (app.thread == null) {
@@ -3085,6 +3086,10 @@ public final class ActiveServices {
updateWhitelistManagerLocked(s.app);
}
}
+ // And do the same for bg activity starts whitelisting.
+ if ((c.flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) {
+ s.updateHasBindingWhitelistingBgActivityStarts();
+ }
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index f9fcef68381e..1751856066fb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -69,6 +69,7 @@ final class ActivityManagerConstants extends ContentObserver {
static final String KEY_SERVICE_MIN_RESTART_TIME_BETWEEN = "service_min_restart_time_between";
static final String KEY_MAX_SERVICE_INACTIVITY = "service_max_inactivity";
static final String KEY_BG_START_TIMEOUT = "service_bg_start_timeout";
+ static final String KEY_SERVICE_BG_ACTIVITY_START_TIMEOUT = "service_bg_activity_start_timeout";
static final String KEY_BOUND_SERVICE_CRASH_RESTART_DURATION = "service_crash_restart_duration";
static final String KEY_BOUND_SERVICE_CRASH_MAX_RETRY = "service_crash_max_retry";
static final String KEY_PROCESS_START_ASYNC = "process_start_async";
@@ -99,6 +100,7 @@ final class ActivityManagerConstants extends ContentObserver {
private static final long DEFAULT_SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
private static final long DEFAULT_MAX_SERVICE_INACTIVITY = 30*60*1000;
private static final long DEFAULT_BG_START_TIMEOUT = 15*1000;
+ private static final long DEFAULT_SERVICE_BG_ACTIVITY_START_TIMEOUT = 10_000;
private static final long DEFAULT_BOUND_SERVICE_CRASH_RESTART_DURATION = 30*60_000;
private static final int DEFAULT_BOUND_SERVICE_CRASH_MAX_RETRY = 16;
private static final boolean DEFAULT_PROCESS_START_ASYNC = true;
@@ -212,6 +214,9 @@ final class ActivityManagerConstants extends ContentObserver {
// allowing the next pending start to run.
public long BG_START_TIMEOUT = DEFAULT_BG_START_TIMEOUT;
+ // For how long after a whitelisted service's start its process can start a background activity
+ public long SERVICE_BG_ACTIVITY_START_TIMEOUT = DEFAULT_SERVICE_BG_ACTIVITY_START_TIMEOUT;
+
// Initial backoff delay for retrying bound foreground services
public long BOUND_SERVICE_CRASH_RESTART_DURATION = DEFAULT_BOUND_SERVICE_CRASH_RESTART_DURATION;
@@ -398,6 +403,9 @@ final class ActivityManagerConstants extends ContentObserver {
DEFAULT_MAX_SERVICE_INACTIVITY);
BG_START_TIMEOUT = mParser.getLong(KEY_BG_START_TIMEOUT,
DEFAULT_BG_START_TIMEOUT);
+ SERVICE_BG_ACTIVITY_START_TIMEOUT = mParser.getLong(
+ KEY_SERVICE_BG_ACTIVITY_START_TIMEOUT,
+ DEFAULT_SERVICE_BG_ACTIVITY_START_TIMEOUT);
BOUND_SERVICE_CRASH_RESTART_DURATION = mParser.getLong(
KEY_BOUND_SERVICE_CRASH_RESTART_DURATION,
DEFAULT_BOUND_SERVICE_CRASH_RESTART_DURATION);
@@ -518,6 +526,8 @@ final class ActivityManagerConstants extends ContentObserver {
pw.println(MAX_SERVICE_INACTIVITY);
pw.print(" "); pw.print(KEY_BG_START_TIMEOUT); pw.print("=");
pw.println(BG_START_TIMEOUT);
+ pw.print(" "); pw.print(KEY_SERVICE_BG_ACTIVITY_START_TIMEOUT); pw.print("=");
+ pw.println(SERVICE_BG_ACTIVITY_START_TIMEOUT);
pw.print(" "); pw.print(KEY_BOUND_SERVICE_CRASH_RESTART_DURATION); pw.print("=");
pw.println(BOUND_SERVICE_CRASH_RESTART_DURATION);
pw.print(" "); pw.print(KEY_BOUND_SERVICE_CRASH_MAX_RETRY); pw.print("=");
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 0387774bb257..eeaa7de85b5c 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -125,6 +125,14 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
int pendingConnectionGroup; // To be filled in to ProcessRecord once it connects
int pendingConnectionImportance; // To be filled in to ProcessRecord once it connects
+ // any current binding to this service has BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS flag?
+ private boolean hasBindingWhitelistingBgActivityStarts;
+ // is this service currently whitelisted to start activities from background by providing
+ // allowBackgroundActivityStarts=true to startServiceLocked()?
+ boolean hasStartedWhitelistingBgActivityStarts;
+ // used to clean up the state of hasStartedWhitelistingBgActivityStarts after a timeout
+ Runnable startedWhitelistingBgActivityStartsCleanUp;
+
String stringName; // caching of toString
private int lastStartId; // identifier of most recent start request.
@@ -371,6 +379,14 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
if (whitelistManager) {
pw.print(prefix); pw.print("whitelistManager="); pw.println(whitelistManager);
}
+ if (hasBindingWhitelistingBgActivityStarts) {
+ pw.print(prefix); pw.print("hasBindingWhitelistingBgActivityStarts=");
+ pw.println(hasBindingWhitelistingBgActivityStarts);
+ }
+ if (hasStartedWhitelistingBgActivityStarts) {
+ pw.print(prefix); pw.print("hasStartedWhitelistingBgActivityStarts=");
+ pw.println(hasStartedWhitelistingBgActivityStarts);
+ }
if (delayed) {
pw.print(prefix); pw.print("delayed="); pw.println(delayed);
}
@@ -518,6 +534,15 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
}
public void setProcess(ProcessRecord _proc) {
+ if (_proc != null) {
+ if (hasStartedWhitelistingBgActivityStarts || hasBindingWhitelistingBgActivityStarts) {
+ _proc.addAllowBackgroundActivityStartsToken(this);
+ } else {
+ _proc.removeAllowBackgroundActivityStartsToken(this);
+ }
+ } else if (app != null) {
+ app.removeAllowBackgroundActivityStartsToken(this);
+ }
app = _proc;
if (pendingConnectionGroup > 0 && _proc != null) {
_proc.connectionService = this;
@@ -540,6 +565,62 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
}
}
+ void updateHasBindingWhitelistingBgActivityStarts() {
+ boolean hasWhitelistingBinding = false;
+ for (int conni = connections.size() - 1; conni >= 0; conni--) {
+ ArrayList<ConnectionRecord> cr = connections.valueAt(conni);
+ for (int i = 0; i < cr.size(); i++) {
+ if ((cr.get(i).flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) {
+ hasWhitelistingBinding = true;
+ break;
+ }
+ }
+ if (hasWhitelistingBinding) {
+ break;
+ }
+ }
+ if (hasBindingWhitelistingBgActivityStarts != hasWhitelistingBinding) {
+ hasBindingWhitelistingBgActivityStarts = hasWhitelistingBinding;
+ updateParentProcessBgActivityStartsWhitelistingToken();
+ }
+ }
+
+ void setHasBindingWhitelistingBgActivityStarts(boolean newValue) {
+ if (hasBindingWhitelistingBgActivityStarts != newValue) {
+ hasBindingWhitelistingBgActivityStarts = newValue;
+ updateParentProcessBgActivityStartsWhitelistingToken();
+ }
+ }
+
+ void setHasStartedWhitelistingBgActivityStarts(boolean newValue) {
+ if (hasStartedWhitelistingBgActivityStarts != newValue) {
+ hasStartedWhitelistingBgActivityStarts = newValue;
+ updateParentProcessBgActivityStartsWhitelistingToken();
+ }
+ }
+
+ /**
+ * Whether the process this service runs in should be temporarily whitelisted to start
+ * activities from background depends on the current state of both
+ * {@code hasStartedWhitelistingBgActivityStarts} and
+ * {@code hasBindingWhitelistingBgActivityStarts}. If either is true, this ServiceRecord
+ * should be contributing as a token in parent ProcessRecord.
+ *
+ * @see com.android.server.am.ProcessRecord#mAllowBackgroundActivityStartsTokens
+ */
+ private void updateParentProcessBgActivityStartsWhitelistingToken() {
+ if (app == null) {
+ return;
+ }
+ if (hasStartedWhitelistingBgActivityStarts || hasBindingWhitelistingBgActivityStarts) {
+ // if the token is already there it's safe to "re-add it" - we're deadling with
+ // a set of Binder objects
+ app.addAllowBackgroundActivityStartsToken(this);
+ } else {
+ app.removeAllowBackgroundActivityStartsToken(this);
+ }
+ }
+
public AppBindRecord retrieveAppBindingLocked(Intent intent,
ProcessRecord app) {
Intent.FilterComparison filter = new Intent.FilterComparison(intent);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
index 66d934541260..2ed25eab50c0 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
@@ -99,8 +99,8 @@ public class AccessibilityServiceConnectionTest {
public void bind_requestsContextToBindService() {
mConnection.bindLocked();
verify(mMockContext).bindServiceAsUser(any(Intent.class), eq(mConnection),
- eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE),
- any(UserHandle.class));
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE
+ | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS), any(UserHandle.class));
}
@Test
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 61d7d6cf45d2..8d2cbca08586 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -357,7 +357,8 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
Intent intent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
intent.setComponent(mComponent);
mBound = mContext.bindServiceAsUser(intent, mConnection,
- Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, new UserHandle(mUser));
+ Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
+ | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, new UserHandle(mUser));
if (!mBound) {
Slog.w(TAG, "Failed binding to voice interaction service " + mComponent);
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 1bf07233fc4d..24690f51f9ce 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -159,7 +159,8 @@ final class VoiceInteractionSessionConnection implements ServiceConnection,
mBindIntent.setComponent(mSessionComponentName);
mBound = mContext.bindServiceAsUser(mBindIntent, this,
Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
- | Context.BIND_ALLOW_OOM_MANAGEMENT, new UserHandle(mUser));
+ | Context.BIND_ALLOW_OOM_MANAGEMENT
+ | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, new UserHandle(mUser));
if (mBound) {
try {
mIWindowManager.addWindowToken(mToken, TYPE_VOICE_INTERACTION, DEFAULT_DISPLAY);
@@ -191,7 +192,8 @@ final class VoiceInteractionSessionConnection implements ServiceConnection,
if (!mFullyBound) {
mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection,
Context.BIND_AUTO_CREATE | Context.BIND_TREAT_LIKE_ACTIVITY
- | Context.BIND_FOREGROUND_SERVICE,
+ | Context.BIND_FOREGROUND_SERVICE
+ | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS,
new UserHandle(mUser));
}