diff options
| author | 2019-03-13 13:44:02 +0000 | |
|---|---|---|
| committer | 2019-03-13 13:44:02 +0000 | |
| commit | 681db90b5aa76e67e4ebf89b3c5c65aabde4c5f4 (patch) | |
| tree | c57b13b688f869215ef0ec7ad0147ee3998f0258 | |
| parent | 15694fcceb739485c07534279210853d83df73fb (diff) | |
| parent | e069b0022f5aa090d00b9266f2760cb2c7a6e97f (diff) | |
Merge "Add new BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS binding flag and the mechanism to use it"
10 files changed, 162 insertions, 52 deletions
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 0c76f3f049a8..5c9931970d5c 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 b437435902df..a750c7917fc2 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -11518,6 +11518,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)); } |