From e069b0022f5aa090d00b9266f2760cb2c7a6e97f Mon Sep 17 00:00:00 2001 From: Michal Karpinski Date: Thu, 7 Mar 2019 16:15:14 +0000 Subject: [PATCH] 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 --- core/java/android/content/Context.java | 9 ++ core/java/android/provider/Settings.java | 1 + .../qs/external/TileLifecycleManager.java | 4 +- .../AccessibilityServiceConnection.java | 3 +- .../com/android/server/am/ActiveServices.java | 93 ++++++++++--------- .../server/am/ActivityManagerConstants.java | 10 ++ .../com/android/server/am/ServiceRecord.java | 81 ++++++++++++++++ .../AccessibilityServiceConnectionTest.java | 4 +- .../VoiceInteractionManagerServiceImpl.java | 3 +- .../VoiceInteractionSessionConnection.java | 6 +- 10 files changed, 162 insertions(+), 52 deletions(-) diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index f896274ed8b35..91ac9e0dcb014 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -337,6 +337,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. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 4836e6c0cba7a..e8f91ca04d63a 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) * * 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 305fbf2e3e984..b135f7b27c3ff 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 a19a84724d451..3bd6220b4767e 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 85ec2dd55e897..627010606b310 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 f9fcef68381e0..1751856066fbd 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 0387774bb257a..eeaa7de85b5c7 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 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 66d9345412607..2ed25eab50c0c 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 61d7d6cf45d29..8d2cbca085864 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 1bf07233fc4d5..24690f51f9ced 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)); }