Merge "Move set speakerphone out of async task executor." into udc-dev
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 10a42de..113d144 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -100,7 +100,7 @@
     <string name="notification_channel_background_calls" msgid="7785659903711350506">"Trucades en segon pla"</string>
     <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Trucades desconnectades"</string>
     <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Aplicacions del telèfon que han fallat"</string>
-    <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Reproducció en continu de trucades"</string>
+    <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Reproducció en directe de trucada"</string>
     <string name="alert_outgoing_call" msgid="5319895109298927431">"En fer aquesta trucada, finalitzarà la de l\'aplicació <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
     <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Tria com vols fer aquesta trucada"</string>
     <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Desvia la trucada amb <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index b151222..57a3fce 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -110,7 +110,7 @@
     <string name="phone_settings_number_not_in_contact_txt" msgid="2602249106007265757">"Броеви што не се наведени во „Контакти“"</string>
     <string name="phone_settings_number_not_in_contact_summary_txt" msgid="963327038085718969">"Блокирани броеви што не се наведени во вашите „Контакти“"</string>
     <string name="phone_settings_private_num_txt" msgid="6339272760338475619">"Приватно"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="6755758240544021037">"Блокирај повикувачи со сокриен број"</string>
+    <string name="phone_settings_private_num_summary_txt" msgid="6755758240544021037">"Блокирај повикувачи со скриен број"</string>
     <string name="phone_settings_payphone_txt" msgid="5003987966052543965">"Телефонска говорница"</string>
     <string name="phone_settings_payphone_summary_txt" msgid="3936631076065563665">"Блокирај повици од телефонски говорници"</string>
     <string name="phone_settings_unknown_txt" msgid="3577926178354772728">"Непознато"</string>
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 7b0b697..dd8e7e8 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -362,7 +362,7 @@
 
     private PhoneAccountHandle mRemotePhoneAccountHandle;
 
-    private UserHandle mInitiatingUser;
+    private UserHandle mAssociatedUser;
 
     private final Handler mHandler = new Handler(Looper.getMainLooper());
 
@@ -830,8 +830,8 @@
                 ? PhoneNumberUtils.extractPostDialPortion(handle.getSchemeSpecificPart()) : "";
         mGatewayInfo = gatewayInfo;
         setConnectionManagerPhoneAccount(connectionManagerPhoneAccountHandle);
-        setTargetPhoneAccount(targetPhoneAccountHandle);
         mCallDirection = callDirection;
+        setTargetPhoneAccount(targetPhoneAccountHandle);
         mIsConference = isConference;
         mShouldAttachToExistingConnection = shouldAttachToExistingConnection
                 || callDirection == CALL_DIRECTION_INCOMING;
@@ -1005,7 +1005,7 @@
         s.append("]");
         s.append(isIncoming() ? "(MT - incoming)" : "(MO - outgoing)");
         s.append("(User=");
-        s.append(getInitiatingUser());
+        s.append(getAssociatedUser());
         s.append(")");
         s.append("\n\t");
 
@@ -1732,15 +1732,13 @@
             mCallStateChangedAtomWriter.setUid(
                     accountHandle.getComponentName().getPackageName(),
                     mContext.getPackageManager());
+            // Set the associated user for the call for MT calls based on the target phone account.
+            if (isIncoming() && !accountHandle.getUserHandle().equals(mAssociatedUser)) {
+                setAssociatedUser(accountHandle.getUserHandle());
+            }
         }
     }
 
-    public UserHandle getUserHandleFromTargetPhoneAccount() {
-        return mTargetPhoneAccountHandle == null
-                ? mCallsManager.getCurrentUserHandle() :
-                mTargetPhoneAccountHandle.getUserHandle();
-    }
-
     public PhoneAccount getPhoneAccountFromHandle() {
         if (getTargetPhoneAccount() == null) {
             return null;
@@ -1985,7 +1983,7 @@
         if (phoneAccount != null) {
             final UserHandle userHandle;
             if (phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
-                userHandle = mInitiatingUser;
+                userHandle = mAssociatedUser;
             } else {
                 userHandle = mTargetPhoneAccountHandle.getUserHandle();
             }
@@ -4017,19 +4015,26 @@
     }
 
     /**
-     * @return user handle of user initiating the outgoing call.
+     * It's possible that the target phone account isn't set when a user hasn't selected a
+     * default sim to place a call. Instead of using the user from the target phone account to
+     * associate the user with a call, we'll use mAssociatedUser instead. For MT calls, we will
+     * continue to use the target phone account user (as it's always set) and for MO calls, we will
+     * use the initiating user instead.
+     *
+     * @return user handle of user associated with the call.
      */
-    public UserHandle getInitiatingUser() {
-        return mInitiatingUser;
+    public UserHandle getAssociatedUser() {
+        return mAssociatedUser;
     }
 
     /**
-     * Set the user handle of user initiating the outgoing call.
-     * @param initiatingUser
+     * Set the user handle of user associated with the call.
+     * @param associatedUser
      */
-    public void setInitiatingUser(UserHandle initiatingUser) {
-        Preconditions.checkNotNull(initiatingUser);
-        mInitiatingUser = initiatingUser;
+    public void setAssociatedUser(UserHandle associatedUser) {
+        Log.i(this, "Setting associated user for call");
+        Preconditions.checkNotNull(associatedUser);
+        mAssociatedUser = associatedUser;
     }
 
     static int getStateFromConnectionState(int state) {
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index f52a966..ff76b9e 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -497,7 +497,7 @@
         boolean allCallSilenced = true;
         synchronized (mCallsManager.getLock()) {
             for (Call call : mRingingCalls) {
-                UserHandle userFromCall = call.getUserHandleFromTargetPhoneAccount();
+                UserHandle userFromCall = call.getAssociatedUser();
                 // Do not try to silence calls when calling user is different from the phone account
                 // user, the account does not have CAPABILITY_MULTI_USER enabled, or if the user
                 // does not have the INTERACT_ACROSS_USERS permission enabled.
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index 55a5df8..4a03726 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -1629,12 +1629,19 @@
         mAvailableRoutes = mDeviceSupportedRoutes & getCurrentCallSupportedRoutes();
         mIsMuted = initState.isMuted();
         mWasOnSpeaker = false;
-        mContext.registerReceiver(mMuteChangeReceiver,
-                new IntentFilter(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED));
-        mContext.registerReceiver(mMuteChangeReceiver,
-                new IntentFilter(AudioManager.STREAM_MUTE_CHANGED_ACTION));
-        mContext.registerReceiver(mSpeakerPhoneChangeReceiver,
-                new IntentFilter(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED));
+        IntentFilter micMuteChangedFilter = new IntentFilter(
+                AudioManager.ACTION_MICROPHONE_MUTE_CHANGED);
+        micMuteChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        mContext.registerReceiver(mMuteChangeReceiver, micMuteChangedFilter);
+
+        IntentFilter muteChangedFilter = new IntentFilter(AudioManager.STREAM_MUTE_CHANGED_ACTION);
+        muteChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        mContext.registerReceiver(mMuteChangeReceiver, muteChangedFilter);
+
+        IntentFilter speakerChangedFilter = new IntentFilter(
+                AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED);
+        speakerChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        mContext.registerReceiver(mSpeakerPhoneChangeReceiver, speakerChangedFilter);
 
         mStatusBarNotifier.notifyMute(initState.isMuted());
         // We used to call mStatusBarNotifier.notifySpeakerphone, but that makes no sense as there
diff --git a/src/com/android/server/telecom/CallEndpointController.java b/src/com/android/server/telecom/CallEndpointController.java
index 82164b3..7e11b47 100644
--- a/src/com/android/server/telecom/CallEndpointController.java
+++ b/src/com/android/server/telecom/CallEndpointController.java
@@ -247,8 +247,9 @@
                     for (BluetoothDevice device : state.getSupportedBluetoothDevices()) {
                         CallEndpoint endpoint = findMatchingBluetoothEndpoint(device);
                         if (endpoint == null) {
+                            String deviceName = device.getName();
                             endpoint = new CallEndpoint(
-                                    device.getName() != null ? device.getName() : "",
+                                    deviceName != null ? deviceName : "",
                                     CallEndpoint.TYPE_BLUETOOTH);
                         }
                         newAvailableEndpoints.add(endpoint);
diff --git a/src/com/android/server/telecom/CallLogManager.java b/src/com/android/server/telecom/CallLogManager.java
index a7bbf84..3005656 100644
--- a/src/com/android/server/telecom/CallLogManager.java
+++ b/src/com/android/server/telecom/CallLogManager.java
@@ -324,7 +324,7 @@
         }
 
         PhoneAccount phoneAccount = mPhoneAccountRegistrar.getPhoneAccountUnchecked(accountHandle);
-        UserHandle initiatingUser = call.getInitiatingUser();
+        UserHandle initiatingUser = call.getAssociatedUser();
         if (phoneAccount != null &&
                 phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
             if (initiatingUser != null &&
diff --git a/src/com/android/server/telecom/CallStreamingController.java b/src/com/android/server/telecom/CallStreamingController.java
index d90524d..1323633 100644
--- a/src/com/android/server/telecom/CallStreamingController.java
+++ b/src/com/android/server/telecom/CallStreamingController.java
@@ -39,9 +39,12 @@
 import android.telecom.Log;
 
 import com.android.internal.telecom.ICallStreamingService;
+import com.android.server.telecom.voip.ParallelTransaction;
+import com.android.server.telecom.voip.SerialTransaction;
 import com.android.server.telecom.voip.VoipCallTransaction;
 import com.android.server.telecom.voip.VoipCallTransactionResult;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionStage;
@@ -179,7 +182,7 @@
             super(mTelecomLock);
             mWrapper = wrapper;
             mCall = call;
-            mUserHandle = mCall.getInitiatingUser();
+            mUserHandle = mCall.getAssociatedUser();
             mContext = context;
         }
 
@@ -265,6 +268,51 @@
         }
     }
 
+    public class StartStreamingTransaction extends SerialTransaction {
+        private Call mCall;
+
+        public StartStreamingTransaction(List<VoipCallTransaction> subTransactions, Call call,
+                TelecomSystem.SyncRoot lock) {
+            super(subTransactions, lock);
+            mCall = call;
+        }
+
+        @Override
+        public void handleTransactionFailure() {
+            mTransactionalServiceWrapper.stopCallStreaming(mCall);
+        }
+    }
+
+    public VoipCallTransaction getStartStreamingTransaction(CallsManager callsManager,
+            TransactionalServiceWrapper wrapper, Call call, TelecomSystem.SyncRoot lock) {
+        // start streaming transaction flow:
+        //     1. make sure there's no ongoing streaming call --> bind to EXO
+        //     2. change audio mode
+        //     3. bind to EXO
+        // If bind to EXO failed, add transaction for stop the streaming
+
+        // create list for multiple transactions
+        List<VoipCallTransaction> transactions = new ArrayList<>();
+        transactions.add(new QueryCallStreamingTransaction(callsManager));
+        transactions.add(new AudioInterceptionTransaction(call, true, lock));
+        transactions.add(getCallStreamingServiceTransaction(
+                callsManager.getContext(), wrapper, call));
+        return new StartStreamingTransaction(transactions, call, lock);
+    }
+
+    public VoipCallTransaction getStopStreamingTransaction(Call call, TelecomSystem.SyncRoot lock) {
+        // TODO: implement this
+        // Stop streaming transaction flow:
+        List<VoipCallTransaction> transactions = new ArrayList<>();
+
+        // 1. unbind to call streaming service
+        transactions.add(getUnbindStreamingServiceTransaction());
+        // 2. audio route operations
+        transactions.add(new CallStreamingController.AudioInterceptionTransaction(call,
+                false, lock));
+        return new ParallelTransaction(transactions, lock);
+    }
+
     @Override
     public void onCallRemoved(Call call) {
         if (mStreamingCall == call) {
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index fa7c2b7..77570c3 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -353,6 +353,16 @@
             new ConcurrentHashMap<Call, Boolean>(8, 0.9f, 1));
 
     /**
+     * List of self-managed calls that have been initialized but not yet added to
+     * CallsManager#addCall(Call). There is a window of time when a Call has been added to Telecom
+     * (e.g. TelecomManager#addNewIncomingCall) to actually added in CallsManager#addCall(Call).
+     * This list is helpful for the NotificationManagerService to know that Telecom is currently
+     * setting up a call which is an important set in making notifications non-dismissible.
+     */
+    private final Set<Call> mSelfManagedCallsBeingSetup = Collections.newSetFromMap(
+            new ConcurrentHashMap<Call, Boolean>(8, 0.9f, 1));
+
+    /**
      * A pending call is one which requires user-intervention in order to be placed.
      * Used by {@link #startCallConfirmation}.
      */
@@ -689,6 +699,7 @@
         // Register BroadcastReceiver to handle enhanced call blocking feature related event.
         IntentFilter intentFilter = new IntentFilter(
                 CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+        intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         intentFilter.addAction(SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED);
         context.registerReceiver(mReceiver, intentFilter, Context.RECEIVER_EXPORTED);
         mGraphHandlerThreads = new LinkedList<>();
@@ -735,7 +746,7 @@
     public void onSuccessfulOutgoingCall(Call call, int callState) {
         Log.v(this, "onSuccessfulOutgoingCall, %s", call);
         call.setPostCallPackageName(getRoleManagerAdapter().getDefaultCallScreeningApp(
-                call.getUserHandleFromTargetPhoneAccount()));
+                call.getAssociatedUser()));
 
         setCallState(call, callState, "successful outgoing call");
         if (!mCalls.contains(call)) {
@@ -799,7 +810,7 @@
     private IncomingCallFilterGraph setUpCallFilterGraph(Call incomingCall) {
         incomingCall.setIsUsingCallFiltering(true);
         String carrierPackageName = getCarrierPackageName();
-        UserHandle userHandle = incomingCall.getUserHandleFromTargetPhoneAccount();
+        UserHandle userHandle = incomingCall.getAssociatedUser();
         String defaultDialerPackageName = TelecomManager.from(mContext).
                 getDefaultDialerPackage(userHandle);
         String userChosenPackageName = getRoleManagerAdapter().
@@ -921,7 +932,7 @@
         if (result.shouldAllowCall) {
             incomingCall.setPostCallPackageName(
                     getRoleManagerAdapter().getDefaultCallScreeningApp(
-                            incomingCall.getUserHandleFromTargetPhoneAccount()
+                            incomingCall.getAssociatedUser()
                     ));
 
             Log.i(this, "onCallFilteringComplete: allow call.");
@@ -1397,6 +1408,8 @@
             // Required for backwards compatibility
             handle = extras.getParcelable(TelephonyManager.EXTRA_INCOMING_NUMBER);
         }
+        PhoneAccount phoneAccount = mPhoneAccountRegistrar.getPhoneAccountUnchecked(
+                phoneAccountHandle);
         Call call = new Call(
                 generateNextCallId(extras),
                 mContext,
@@ -1413,6 +1426,15 @@
                 isConference, /* isConference */
                 mClockProxy,
                 mToastFactory);
+        // Ensure new calls related to self-managed calls/connections are set as such. This will
+        // be overridden when the actual connection is returned in startCreateConnection, however
+        // doing this now ensures the logs and any other logic will treat this call as self-managed
+        // from the moment it is created.
+        boolean isSelfManaged = phoneAccount != null && phoneAccount.isSelfManaged();
+        call.setIsSelfManaged(isSelfManaged);
+        // It's important to start tracking self-managed calls as soon as the Call object is
+        // initialized so NotificationManagerService is aware Telecom is setting up a call
+        if (isSelfManaged) mSelfManagedCallsBeingSetup.add(call);
 
         // set properties for transactional call
         if (extras.containsKey(TelecomManager.TRANSACTION_CALL_ID_KEY)) {
@@ -1430,18 +1452,11 @@
                 }
             }
             // Incoming address was set via EXTRA_INCOMING_CALL_ADDRESS above.
-            call.setInitiatingUser(phoneAccountHandle.getUserHandle());
+            call.setAssociatedUser(phoneAccountHandle.getUserHandle());
         }
 
-        // Ensure new calls related to self-managed calls/connections are set as such. This will
-        // be overridden when the actual connection is returned in startCreateConnection, however
-        // doing this now ensures the logs and any other logic will treat this call as self-managed
-        // from the moment it is created.
-        PhoneAccount phoneAccount = mPhoneAccountRegistrar.getPhoneAccountUnchecked(
-                phoneAccountHandle);
         if (phoneAccount != null) {
             Bundle phoneAccountExtras = phoneAccount.getExtras();
-            call.setIsSelfManaged(phoneAccount.isSelfManaged());
             if (call.isSelfManaged()) {
                 // Self managed calls will always be voip audio mode.
                 call.setIsVoipAudioMode(true);
@@ -1557,7 +1572,14 @@
         // Check if the target phone account is possibly in ECBM.
         call.setIsInECBM(getEmergencyCallHelper()
                 .isLastOutgoingEmergencyCallPAH(call.getTargetPhoneAccount()));
-        if (mUserManager.isQuietModeEnabled(call.getUserHandleFromTargetPhoneAccount())
+        // If the phone account user profile is paused or the call isn't visible to the secondary/
+        // guest user, reject the non-emergency incoming call. When the current user is the admin,
+        // we need to allow the calls to go through if the work profile isn't paused. We should
+        // always allow emergency calls and also allow non-emergency calls when ECBM is active for
+        // the phone account.
+        if ((mUserManager.isQuietModeEnabled(call.getAssociatedUser())
+                || (!mUserManager.isUserAdmin(mCurrentUserHandle.getIdentifier())
+                && !isCallVisibleForUser(call, mCurrentUserHandle)))
                 && !call.isEmergencyCall() && !call.isInECBM()) {
             Log.d(TAG, "Rejecting non-emergency call because the owner %s is not running.",
                     phoneAccountHandle.getUserHandle());
@@ -1634,6 +1656,8 @@
                 mToastFactory);
         call.initAnalytics();
 
+        // For unknown calls, base the associated user off of the target phone account handle.
+        call.setAssociatedUser(phoneAccountHandle.getUserHandle());
         setIntentExtrasAndStartTime(call, extras);
         call.addListener(this);
         notifyStartCreateConnection(call);
@@ -1742,7 +1766,7 @@
                     isConference ? participants : null,
                     null /* gatewayInfo */,
                     null /* connectionManagerPhoneAccount */,
-                    null /* requestedAccountHandle */,
+                    requestedAccountHandle /* targetPhoneAccountHandle */,
                     Call.CALL_DIRECTION_OUTGOING /* callDirection */,
                     false /* forceAttachToExistingConnection */,
                     isConference, /* isConference */
@@ -1763,7 +1787,6 @@
                                 TelecomManager.PRESENTATION_ALLOWED);
                     }
                 }
-                call.setTargetPhoneAccount(requestedAccountHandle);
             }
 
             call.initAnalytics(callingPackage, creationLogs.toString());
@@ -1797,11 +1820,14 @@
                         || phoneAccountExtra.getBoolean(
                                 PhoneAccount.EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE, true));
             }
-            call.setInitiatingUser(initiatingUser);
+            call.setAssociatedUser(initiatingUser);
             isReusedCall = false;
         } else {
             isReusedCall = true;
         }
+        // It's important to start tracking self-managed calls as soon as the Call object is
+        // initialized so NotificationManagerService is aware Telecom is setting up a call
+        if (isSelfManaged) mSelfManagedCallsBeingSetup.add(call);
 
         int videoState = VideoProfile.STATE_AUDIO_ONLY;
         if (extras != null) {
@@ -2073,7 +2099,7 @@
                     (callPhoneAccountHandlePair, uriCallerInfoPair) -> {
                         Call theCall = callPhoneAccountHandlePair.first;
                         UserHandle userHandleForCallScreening = theCall.
-                                getUserHandleFromTargetPhoneAccount();
+                                getAssociatedUser();
                         boolean isInContacts = uriCallerInfoPair.second != null
                                 && uriCallerInfoPair.second.contactExists;
                         Log.d(CallsManager.this, "outgoingCallIdStage: isInContacts=%s",
@@ -2308,7 +2334,7 @@
         // Find the user chosen call screening app.
         String callScreeningApp =
                 mRoleManagerAdapter.getDefaultCallScreeningApp(
-                        theCall.getUserHandleFromTargetPhoneAccount());
+                        theCall.getAssociatedUser());
 
         CompletableFuture future =
                 new CallScreeningServiceHelper(mContext,
@@ -2472,7 +2498,7 @@
                 && !phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
             // Note that mCurrentUserHandle may not actually be the current user, i.e.
             // in the case of work profiles
-            UserHandle currentUserHandle = call.getUserHandleFromTargetPhoneAccount();
+            UserHandle currentUserHandle = call.getAssociatedUser();
             // Check if the phoneAccountHandle belongs to the current user
             if (phoneAccountHandle != null &&
                     !phoneAccountHandle.getUserHandle().equals(currentUserHandle)) {
@@ -2755,7 +2781,7 @@
         // Auto-enable speakerphone if the originating intent specified to do so, if the call
         // is a video call, of if using speaker when docked
         PhoneAccount account = mPhoneAccountRegistrar.getPhoneAccount(
-                call.getTargetPhoneAccount(), call.getInitiatingUser());
+                call.getTargetPhoneAccount(), call.getAssociatedUser());
         boolean allowVideo = false;
         if (account != null) {
             allowVideo = account.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING);
@@ -2817,7 +2843,7 @@
             }
         } else if (mPhoneAccountRegistrar.getCallCapablePhoneAccounts(
                 requireCallCapableAccountByHandle ? callHandleScheme : null, false,
-                call.getInitiatingUser(), false).isEmpty()) {
+                call.getAssociatedUser(), false).isEmpty()) {
             // If there are no call capable accounts, disconnect the call.
             markCallAsDisconnected(call, new DisconnectCause(DisconnectCause.CANCELED,
                     "No registered PhoneAccounts"));
@@ -3438,7 +3464,7 @@
         } else {
             if (setDefault) {
                 mPhoneAccountRegistrar
-                        .setUserSelectedOutgoingPhoneAccount(account, call.getInitiatingUser());
+                        .setUserSelectedOutgoingPhoneAccount(account, call.getAssociatedUser());
             }
 
             if (mPendingAccountSelection != null) {
@@ -4144,6 +4170,8 @@
         call.setVideoProvider(parcelableConference.getVideoProvider());
         call.setStatusHints(parcelableConference.getStatusHints());
         call.putConnectionServiceExtras(parcelableConference.getExtras());
+        // For conference calls, set the associated user from the target phone account user handle.
+        call.setAssociatedUser(phoneAccount.getUserHandle());
         // In case this Conference was added via a ConnectionManager, keep track of the original
         // Connection ID as created by the originating ConnectionService.
         Bundle extras = parcelableConference.getExtras();
@@ -4236,6 +4264,7 @@
         Log.i(this, "addCall(%s)", call);
         call.addListener(this);
         mCalls.add(call);
+        mSelfManagedCallsBeingSetup.remove(call);
 
         // Specifies the time telecom finished routing the call. This is used by the dialer for
         // analytics.
@@ -4279,6 +4308,7 @@
             mCalls.remove(call);
             shouldNotify = true;
         }
+        mSelfManagedCallsBeingSetup.remove(call);
 
         call.destroy();
         updateExternalCallCanPullSupport();
@@ -4536,8 +4566,10 @@
      * @return {@code true} if the app has ongoing calls, or {@code false} otherwise.
      */
     public boolean isInSelfManagedCall(String packageName, UserHandle userHandle) {
-        return mCalls.stream().anyMatch(
-                c -> c.isSelfManaged()
+        return mSelfManagedCallsBeingSetup.stream().anyMatch(c -> c.isSelfManaged()
+                && c.getTargetPhoneAccount().getComponentName().getPackageName().equals(packageName)
+                && c.getTargetPhoneAccount().getUserHandle().equals(userHandle)) ||
+                mCalls.stream().anyMatch(c -> c.isSelfManaged()
                 && c.getTargetPhoneAccount().getComponentName().getPackageName().equals(packageName)
                 && c.getTargetPhoneAccount().getUserHandle().equals(userHandle));
     }
@@ -4729,11 +4761,14 @@
     }
 
     /**
-     * Determines if there are any self-managed calls.
+     * Note: isInSelfManagedCall(packageName, UserHandle) should always be used in favor or this
+     * method. This method determines if there are any self-managed calls globally.
      * @return {@code true} if there are self-managed calls, {@code false} otherwise.
      */
+    @VisibleForTesting
     public boolean hasSelfManagedCalls() {
-        return mCalls.stream().filter(call -> call.isSelfManaged()).count() > 0;
+        return mSelfManagedCallsBeingSetup.size() > 0 ||
+                mCalls.stream().filter(call -> call.isSelfManaged()).count() > 0;
     }
 
     /**
@@ -5181,6 +5216,9 @@
         call.setHandle(connection.getHandle(), connection.getHandlePresentation());
         call.setCallerDisplayName(connection.getCallerDisplayName(),
                 connection.getCallerDisplayNamePresentation());
+        // For existing connections, use the phone account user handle to determine the user
+        // association with the call.
+        call.setAssociatedUser(connection.getPhoneAccount().getUserHandle());
         call.addListener(this);
         call.putConnectionServiceExtras(connection.getExtras());
 
@@ -5830,7 +5868,9 @@
         if (isSelfManaged) {
             call.setIsVoipAudioMode(true);
         }
-        call.setInitiatingUser(getCurrentUserHandle());
+        // Set associated user based on the existing call as it doesn't make sense to handover calls
+        // across user profiles.
+        call.setAssociatedUser(handoverFromCall.getAssociatedUser());
 
         // Ensure we don't try to place an outgoing call with video if video is not
         // supported.
@@ -6064,6 +6104,9 @@
         fromCall.setHandoverDestinationCall(call);
         call.setHandoverSourceCall(fromCall);
         call.setHandoverState(HandoverState.HANDOVER_TO_STARTED);
+        // Set associated user based on the existing call as it doesn't make sense to handover calls
+        // across user profiles.
+        call.setAssociatedUser(fromCall.getAssociatedUser());
         fromCall.setHandoverState(HandoverState.HANDOVER_FROM_STARTED);
 
         if (isSpeakerEnabledForVideoCalls() && VideoProfile.isVideo(videoState)) {
@@ -6350,7 +6393,7 @@
      * @return {@code true} if call is visible to the calling user
      */
     boolean isCallVisibleForUser(Call call, UserHandle userHandle) {
-        return call.getUserHandleFromTargetPhoneAccount().equals(userHandle)
+        return call.getAssociatedUser().equals(userHandle)
                 || call.getPhoneAccountFromHandle()
                 .hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER);
     }
@@ -6480,4 +6523,14 @@
         }
         call.getTransactionServiceWrapper().stopCallStreaming(call);
     }
+
+    @VisibleForTesting
+    public Set<Call> getSelfManagedCallsBeingSetup() {
+        return mSelfManagedCallsBeingSetup;
+    }
+
+    @VisibleForTesting
+    public void addCallBeingSetup(Call call) {
+        mSelfManagedCallsBeingSetup.add(call);
+    }
 }
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
old mode 100644
new mode 100755
index 5b727ab..c550ede
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -26,6 +26,7 @@
 import android.location.Location;
 import android.location.LocationManager;
 import android.location.LocationRequest;
+import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -100,10 +101,17 @@
                 ParcelableConnection connection, Session.Info sessionInfo) {
             Log.startSession(sessionInfo, LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE,
                     mPackageAbbreviation);
+            UserHandle callingUserHandle = Binder.getCallingUserHandle();
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
                     logIncoming("handleCreateConnectionComplete %s", callId);
+                    // Check status hints image for cross user access
+                    if (connection.getStatusHints() != null) {
+                        Icon icon = connection.getStatusHints().getIcon();
+                        connection.getStatusHints().setIcon(StatusHints.
+                                validateAccountIconUserBoundary(icon, callingUserHandle));
+                    }
                     ConnectionServiceWrapper.this
                             .handleCreateConnectionComplete(callId, request, connection);
 
@@ -504,6 +512,14 @@
             Log.startSession(sessionInfo, LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL,
                     mPackageAbbreviation);
 
+            UserHandle callingUserHandle = Binder.getCallingUserHandle();
+            // Check status hints image for cross user access
+            if (parcelableConference.getStatusHints() != null) {
+                Icon icon = parcelableConference.getStatusHints().getIcon();
+                parcelableConference.getStatusHints().setIcon(StatusHints.
+                        validateAccountIconUserBoundary(icon, callingUserHandle));
+            }
+
             if (parcelableConference.getConnectElapsedTimeMillis() != 0
                     && mContext.checkCallingOrSelfPermission(MODIFY_PHONE_STATE)
                             != PackageManager.PERMISSION_GRANTED) {
@@ -769,10 +785,17 @@
         public void setStatusHints(String callId, StatusHints statusHints,
                 Session.Info sessionInfo) {
             Log.startSession(sessionInfo, "CSW.sSH", mPackageAbbreviation);
+            UserHandle callingUserHandle = Binder.getCallingUserHandle();
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
                     logIncoming("setStatusHints %s %s", callId, statusHints);
+                    // Check status hints image for cross user access
+                    if (statusHints != null) {
+                        Icon icon = statusHints.getIcon();
+                        statusHints.setIcon(StatusHints.validateAccountIconUserBoundary(
+                                icon, callingUserHandle));
+                    }
                     Call call = mCallIdMapper.getCall(callId);
                     if (call != null) {
                         call.setStatusHints(statusHints);
@@ -1007,6 +1030,14 @@
                                     connection.getCallDirection(),
                                     connection.getCallerNumberVerificationStatus());
                         }
+
+                        // Check status hints image for cross user access
+                        if (connection.getStatusHints() != null) {
+                            Icon icon = connection.getStatusHints().getIcon();
+                            connection.getStatusHints().setIcon(StatusHints.
+                                    validateAccountIconUserBoundary(icon, userHandle));
+                        }
+
                         // Check to see if this Connection has already been added.
                         Call alreadyAddedConnection = mCallsManager
                                 .getAlreadyAddedConnection(connectIdToCheck);
diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java
index 6702f03..19691c1 100644
--- a/src/com/android/server/telecom/CreateConnectionProcessor.java
+++ b/src/com/android/server/telecom/CreateConnectionProcessor.java
@@ -391,7 +391,7 @@
             // current user.
             // ONLY include phone accounts which are NOT self-managed; we will never consider a self
             // managed phone account for placing an emergency call.
-            UserHandle userFromCall = mCall.getUserHandleFromTargetPhoneAccount();
+            UserHandle userFromCall = mCall.getAssociatedUser();
             List<PhoneAccount> allAccounts = mPhoneAccountRegistrar
                     .getAllPhoneAccounts(userFromCall, false)
                     .stream()
diff --git a/src/com/android/server/telecom/DefaultDialerCache.java b/src/com/android/server/telecom/DefaultDialerCache.java
index 3ce394e..dc79715 100644
--- a/src/com/android/server/telecom/DefaultDialerCache.java
+++ b/src/com/android/server/telecom/DefaultDialerCache.java
@@ -160,6 +160,7 @@
         packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         packageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
         packageIntentFilter.addDataScheme("package");
+        packageIntentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         context.registerReceiverAsUser(mReceiver, UserHandle.ALL, packageIntentFilter, null, null);
 
         IntentFilter bootIntentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
diff --git a/src/com/android/server/telecom/DockManager.java b/src/com/android/server/telecom/DockManager.java
index dda5711..114672e 100644
--- a/src/com/android/server/telecom/DockManager.java
+++ b/src/com/android/server/telecom/DockManager.java
@@ -76,6 +76,7 @@
 
         // Register for misc other intent broadcasts.
         IntentFilter intentFilter = new IntentFilter(Intent.ACTION_DOCK_EVENT);
+        intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         context.registerReceiver(mReceiver, intentFilter);
     }
 
diff --git a/src/com/android/server/telecom/HeadsetMediaButton.java b/src/com/android/server/telecom/HeadsetMediaButton.java
index 8e9caff..7458f54 100644
--- a/src/com/android/server/telecom/HeadsetMediaButton.java
+++ b/src/com/android/server/telecom/HeadsetMediaButton.java
@@ -23,16 +23,11 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.telecom.CallAudioState;
-import android.telecom.CallEndpoint;
 import android.telecom.Log;
-import android.util.ArraySet;
 import android.view.KeyEvent;
 
 import com.android.internal.annotations.VisibleForTesting;
 
-import java.util.Set;
-
 /**
  * Static class to handle listening to the headset media buttons.
  */
@@ -154,10 +149,8 @@
     private final Context mContext;
     private final CallsManager mCallsManager;
     private final TelecomSystem.SyncRoot mLock;
-    private final Set<Call> mCalls = new ArraySet<>();
     private MediaSessionAdapter mSession;
     private KeyEvent mLastHookEvent;
-    private @CallEndpoint.EndpointType int mCurrentEndpointType;
 
     /**
      * Constructor used for testing purposes to initialize a {@link HeadsetMediaButton} with a
@@ -219,7 +212,7 @@
             return mCallsManager.onMediaButton(LONG_PRESS);
         } else if (event.getAction() == KeyEvent.ACTION_UP) {
             // We should not judge SHORT_PRESS by ACTION_UP event repeatCount, because it always
-            // returns 0.
+            // return 0.
             // Actually ACTION_DOWN event repeatCount only increases when LONG_PRESS performed.
             if (mLastHookEvent != null && mLastHookEvent.getRepeatCount() == 0) {
                 return mCallsManager.onMediaButton(SHORT_PRESS);
@@ -233,70 +226,50 @@
         return true;
     }
 
-    @Override
-    public void onCallEndpointChanged(CallEndpoint callEndpoint) {
-        mCurrentEndpointType = callEndpoint.getEndpointType();
-        Log.i(this, "onCallEndpointChanged: endPoint=%s", callEndpoint);
-        maybeChangeSessionState();
-    }
-
     /** ${inheritDoc} */
     @Override
     public void onCallAdded(Call call) {
-        handleCallAddition(call);
+        if (call.isExternalCall()) {
+            return;
+        }
+        handleCallAddition();
     }
 
     /**
      * Triggers session activation due to call addition.
      */
-    private void handleCallAddition(Call call) {
-        mCalls.add(call);
-        maybeChangeSessionState();
+    private void handleCallAddition() {
+        mMediaSessionHandler.obtainMessage(MSG_MEDIA_SESSION_SET_ACTIVE, 1, 0).sendToTarget();
+    }
+
+    /** ${inheritDoc} */
+    @Override
+    public void onCallRemoved(Call call) {
+        if (call.isExternalCall()) {
+            return;
+        }
+        handleCallRemoval();
     }
 
     /**
-     * Based on whether there are tracked calls and the audio is routed to a wired headset,
-     * potentially activate or deactive the media session.
+     * Triggers session deactivation due to call removal.
      */
-    private void maybeChangeSessionState() {
-        boolean hasNonExternalCalls = !mCalls.isEmpty()
-                && mCalls.stream().anyMatch(c -> !c.isExternalCall());
-        if (hasNonExternalCalls && mCurrentEndpointType == CallEndpoint.TYPE_WIRED_HEADSET) {
-            Log.i(this, "maybeChangeSessionState: hasCalls=%b, currentEndpointType=%s, ACTIVATE",
-                    hasNonExternalCalls, CallEndpoint.endpointTypeToString(mCurrentEndpointType));
-            mMediaSessionHandler.obtainMessage(MSG_MEDIA_SESSION_SET_ACTIVE, 1, 0).sendToTarget();
-        } else {
-            Log.i(this, "maybeChangeSessionState: hasCalls=%b, currentEndpointType=%s, DEACTIVATE",
-                    hasNonExternalCalls, CallEndpoint.endpointTypeToString(mCurrentEndpointType));
+    private void handleCallRemoval() {
+        if (!mCallsManager.hasAnyCalls()) {
             mMediaSessionHandler.obtainMessage(MSG_MEDIA_SESSION_SET_ACTIVE, 0, 0).sendToTarget();
         }
     }
 
     /** ${inheritDoc} */
     @Override
-    public void onCallRemoved(Call call) {
-        handleCallRemoval(call);
-    }
-
-    /**
-     * Triggers session deactivation due to call removal.
-     */
-    private void handleCallRemoval(Call call) {
-        // If we were tracking the call, potentially change session state.
-        if (mCalls.remove(call)) {
-            if (mCalls.isEmpty()) {
-                // When there are no calls, don't cache that we previously had a wired headset
-                // connected; we'll be updated on the next call.
-                mCurrentEndpointType = CallEndpoint.TYPE_UNKNOWN;
-            }
-            maybeChangeSessionState();
-        }
-    }
-
-    /** ${inheritDoc} */
-    @Override
     public void onExternalCallChanged(Call call, boolean isExternalCall) {
-        maybeChangeSessionState();
+        // Note: We don't use the onCallAdded/onCallRemoved methods here since they do checks to see
+        // if the call is external or not and would skip the session activation/deactivation.
+        if (isExternalCall) {
+            handleCallRemoval();
+        } else {
+            handleCallAddition();
+        }
     }
 
     @VisibleForTesting
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index 3d3e3b4..d5689ae 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -47,6 +47,7 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.permission.PermissionManager;
 import android.telecom.CallAudioState;
 import android.telecom.CallEndpoint;
 import android.telecom.ConnectionService;
@@ -146,16 +147,20 @@
         private long mBindingStartTime;
         private long mDisconnectTime;
 
+        private boolean mHasCrossUserOrProfilePerm;
+
         public InCallServiceInfo(ComponentName componentName,
                 boolean isExternalCallsSupported,
                 boolean isSelfManageCallsSupported,
-                int type) {
+                int type, boolean hasCrossUserOrProfilePerm) {
             mComponentName = componentName;
             mIsExternalCallsSupported = isExternalCallsSupported;
             mIsSelfManagedCallsSupported = isSelfManageCallsSupported;
             mType = type;
+            mHasCrossUserOrProfilePerm = hasCrossUserOrProfilePerm;
         }
 
+        public boolean hasCrossUserOrProfilePermission() { return mHasCrossUserOrProfilePerm; }
         public ComponentName getComponentName() {
             return mComponentName;
         }
@@ -292,8 +297,19 @@
         private boolean mIsNullBinding = false;
         private NotificationManager mNotificationManager;
 
+        //this is really used for cases where the userhandle for a call
+        //does not match what we want to use for bindAsUser
+        private final UserHandle mUserHandleToUseForBinding;
+
         public InCallServiceBindingConnection(InCallServiceInfo info) {
             mInCallServiceInfo = info;
+            mUserHandleToUseForBinding = null;
+        }
+
+        public InCallServiceBindingConnection(InCallServiceInfo info,
+                UserHandle userHandleToUseForBinding) {
+            mInCallServiceInfo = info;
+            mUserHandleToUseForBinding = userHandleToUseForBinding;
         }
 
         @Override
@@ -335,14 +351,31 @@
             Log.i(this, "Attempting to bind to InCall %s, with %s", mInCallServiceInfo, intent);
             mIsConnected = true;
             mInCallServiceInfo.setBindingStartTime(mClockProxy.elapsedRealtime());
-            UserHandle userToBind = getUserFromCall(call);
-            boolean isManagedProfile = UserUtil.isManagedProfile(mContext, userToBind);
+            boolean isManagedProfile = UserUtil.isManagedProfile(mContext, userFromCall);
             // Note that UserHandle.CURRENT fails to capture the work profile, so we need to handle
             // it separately to ensure that the ICS is bound to the appropriate user. If ECBM is
             // active, we know that a work sim was previously used to place a MO emergency call. We
             // need to ensure that we bind to the CURRENT_USER in this case, as the work user would
             // not be running (handled in getUserFromCall).
-            userToBind = isManagedProfile ? userToBind : UserHandle.CURRENT;
+            UserHandle userToBind = isManagedProfile ? userFromCall : UserHandle.CURRENT;
+            if ((mInCallServiceInfo.mType == IN_CALL_SERVICE_TYPE_NON_UI
+                    || mInCallServiceInfo.mType == IN_CALL_SERVICE_TYPE_CAR_MODE_UI) && (
+                    mUserHandleToUseForBinding != null)) {
+                //guarding change for non-UI/carmode-UI services which may not be present for
+                // work profile.
+                //In this case, we use the parent user handle. (This also seems to be more
+                // accurate that USER_CURRENT since we queried/discovered the packages using the
+                // parent handle)
+                if (mInCallServiceInfo.hasCrossUserOrProfilePermission()) {
+                    userToBind = mUserHandleToUseForBinding;
+                } else {
+                    Log.i(this,
+                            "service does not have INTERACT_ACROSS_PROFILES or "
+                                    + "INTERACT_ACROSS_USERS permission");
+                }
+            }
+            Log.i(this, "using user id: %s for binding. User from Call is: %s", userToBind,
+                    userFromCall);
             if (!mContext.bindServiceAsUser(intent, mServiceConnection,
                     Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
                         | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS
@@ -668,7 +701,7 @@
                 }
 
                 mCarModeConnection = mCurrentConnection =
-                        new InCallServiceBindingConnection(carModeConnectionInfo);
+                        new InCallServiceBindingConnection(carModeConnectionInfo, userHandle);
                 mIsCarMode = true;
 
                 int result = mCurrentConnection.connect(null);
@@ -960,34 +993,137 @@
         }
     };
 
+    private UserHandle findChildManagedProfileUser(UserHandle parent, UserManager um) {
+        UserHandle childManagedProfileUser = null;
+
+        //find child managed profile user (if any)
+        List<UserHandle> allUsers = um.getAllProfiles();
+        for (UserHandle u : allUsers) {
+            if ((um.getProfileParent(u) != null) && (um.getProfileParent(u).equals(parent))
+                    && um.isManagedProfile(u.getIdentifier())) {
+                //found managed profile child
+                Log.i(this,
+                        "Child managed profile user found: " + u.getIdentifier());
+                childManagedProfileUser = u;
+                break;
+            }
+        }
+        return childManagedProfileUser;
+    }
     private BroadcastReceiver mPackageChangedReceiver = new BroadcastReceiver() {
+        private List<InCallController.InCallServiceInfo> getNonUiInCallServiceInfoList(
+                Intent intent, UserHandle userHandle) {
+            String changedPackage = intent.getData().getSchemeSpecificPart();
+            List<InCallController.InCallServiceInfo> inCallServiceInfoList =
+                    Arrays.stream(intent.getStringArrayExtra(
+                                    Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST))
+                            .map((className) ->
+                                    ComponentName.createRelative(changedPackage,
+                                            className))
+                            .filter(mKnownNonUiInCallServices::contains)
+                            .flatMap(componentName -> getInCallServiceComponents(
+                                    userHandle, componentName,
+                                    IN_CALL_SERVICE_TYPE_NON_UI).stream())
+                            .collect(Collectors.toList());
+            return ((inCallServiceInfoList != null) ? inCallServiceInfoList : new ArrayList<>());
+        }
+
+        //Here we query components using the userHandle. We then also query components using the
+        //parent userHandle (if any) while removing duplicates. For non-dup components found using
+        //parent userHandle, we use the overloaded InCallServiceBindingConnection constructor.
+        @SuppressWarnings("ReturnValueIgnored")
+        private List<InCallServiceBindingConnection> getNonUiInCallServiceBindingConnectionList(
+                Intent intent, @NonNull UserHandle userHandle, UserHandle parentUserHandle) {
+            List<InCallServiceBindingConnection> result = new ArrayList<>();
+            List<InCallController.InCallServiceInfo> serviceInfoListForParent = new ArrayList<>();
+
+            //query and add components for the child
+            List<InCallController.InCallServiceInfo> serviceInfoListForUser =
+                    getNonUiInCallServiceInfoList(intent, userHandle);
+
+            //if user has a parent, get components for parents
+            if (parentUserHandle != null) {
+                serviceInfoListForParent = getNonUiInCallServiceInfoList(intent, parentUserHandle);
+            }
+
+            serviceInfoListForUser
+                    .stream()
+                    .map(InCallServiceBindingConnection::new)
+                    .collect(Collectors.toCollection(() -> result));
+
+            serviceInfoListForParent
+                    .stream()
+                    .filter((e) -> !(serviceInfoListForUser.contains(e)))
+                    .map((serviceinfo) -> new InCallServiceBindingConnection(serviceinfo,
+                            parentUserHandle))
+                    .collect(Collectors.toCollection(() -> result));
+
+            return result;
+        }
+
         @Override
         public void onReceive(Context context, Intent intent) {
             Log.startSession("ICC.pCR");
+            UserManager um = mContext.getSystemService(UserManager.class);
             try {
                 if (Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())) {
                     synchronized (mLock) {
-                        String changedPackage = intent.getData().getSchemeSpecificPart();
                         int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
                         UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
-                        List<InCallServiceBindingConnection> componentsToBind =
-                                Arrays.stream(intent.getStringArrayExtra(
-                                        Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST))
-                                        .map((className) ->
-                                                ComponentName.createRelative(changedPackage,
-                                                        className))
-                                        .filter(mKnownNonUiInCallServices::contains)
-                                        .flatMap(componentName -> getInCallServiceComponents(
-                                                userHandle, componentName,
-                                                IN_CALL_SERVICE_TYPE_NON_UI).stream())
-                                        .map(InCallServiceBindingConnection::new)
-                                        .collect(Collectors.toList());
+                        boolean isManagedProfile = um.isManagedProfile(userHandle.getIdentifier());
 
-                        if (mNonUIInCallServiceConnections.containsKey(userHandle)) {
-                            mNonUIInCallServiceConnections.get(userHandle).
-                                    addConnections(componentsToBind);
+                        /*
+                        There are two possibilities here:
+                         1) We get a work-profile/managed userHandle. In this case we need to check
+                         if there are any ongoing calls for that user. If yes, then process further
+                         by querying component using this user handle (also bindAsUser using this
+                          handle). Else safely ignore it.
+                                OR
+                         2) We get the primary/non-managed userHandle. In this case, we have two
+                          sub-cases to handle:
+                                   a) If there are ongoing calls for this user, query components
+                                   using this user and addConnections
+                                   b) If there are ongoing calls for the child of this user, we
+                                   also addConnections to that child (but invoke bindAsUser later
+                                    with the parent handle).
+
+                         */
+
+                        UserHandle childManagedProfileUser = findChildManagedProfileUser(
+                                userHandle, um);
+                        boolean isUserKeyPresent = mNonUIInCallServiceConnections.containsKey(
+                                userHandle);
+                        boolean isChildUserKeyPresent = (childManagedProfileUser == null) ? false
+                                : mNonUIInCallServiceConnections.containsKey(
+                                        childManagedProfileUser);
+                        List<InCallServiceBindingConnection> componentsToBindForUser = null;
+                        List<InCallServiceBindingConnection> componentsToBindForChild = null;
+
+                        if(isUserKeyPresent) {
+                            componentsToBindForUser =
+                                    getNonUiInCallServiceBindingConnectionList(intent,
+                                            userHandle, null);
+                        }
+                        if (isChildUserKeyPresent) {
+                            componentsToBindForChild =
+                                    getNonUiInCallServiceBindingConnectionList(intent,
+                                            childManagedProfileUser, userHandle);
                         }
 
+                        Log.i(this,
+                                "isUserKeyPresent:%b isChildKeyPresent:%b isManagedProfile:%b "
+                                        + "user:%d",
+                                isUserKeyPresent, isChildUserKeyPresent, isManagedProfile,
+                                userHandle.getIdentifier());
+
+                        if (isUserKeyPresent && componentsToBindForUser != null) {
+                            mNonUIInCallServiceConnections.get(userHandle).
+                                    addConnections(componentsToBindForUser);
+                        }
+                        if (isChildUserKeyPresent && componentsToBindForChild != null) {
+                            mNonUIInCallServiceConnections.get(childManagedProfileUser).
+                                    addConnections(componentsToBindForChild);
+                        }
                         // If the current car mode app become enabled from disabled, update
                         // the connection to binding
                         updateCarModeForConnections();
@@ -1119,7 +1255,9 @@
         mSystemStateHelper.addListener(mSystemStateListener);
         mClockProxy = clockProxy;
         restrictPhoneCallOps();
-        mContext.registerReceiver(mUserAddedReceiver, new IntentFilter(Intent.ACTION_USER_ADDED));
+        IntentFilter userAddedFilter = new IntentFilter(Intent.ACTION_USER_ADDED);
+        userAddedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        mContext.registerReceiver(mUserAddedReceiver, userAddedFilter);
     }
 
     private void restrictPhoneCallOps() {
@@ -1569,6 +1707,11 @@
         return mInCallServices;
     }
 
+    @VisibleForTesting
+    public Map<UserHandle, CarSwappingInCallServiceConnection> getInCallServiceConnections() {
+        return mInCallServiceConnections;
+    }
+
     void silenceRinger(Set<UserHandle> userHandles) {
         userHandles.forEach(userHandle -> {
             if (mInCallServices.containsKey(userHandle)) {
@@ -1689,6 +1832,14 @@
     @VisibleForTesting
     public void bindToServices(Call call) {
         UserHandle userFromCall = getUserFromCall(call);
+        UserHandle parentUser = null;
+        UserManager um = mContext.getSystemService(UserManager.class);
+
+        if (um.isManagedProfile(userFromCall.getIdentifier())) {
+            parentUser = um.getProfileParent(userFromCall);
+            Log.i(this, "child:%s  parent:%s", userFromCall, parentUser);
+        }
+
         if (!mInCallServiceConnections.containsKey(userFromCall)) {
             InCallServiceConnection dialerInCall = null;
             InCallServiceInfo defaultDialerComponentInfo = getDefaultDialerComponent(userFromCall);
@@ -1708,10 +1859,24 @@
 
             InCallServiceConnection carModeInCall = null;
             InCallServiceInfo carModeComponentInfo = getCurrentCarModeComponent(userFromCall);
+            InCallServiceInfo carModeComponentInfoForParentUser = null;
+            if(parentUser != null) {
+                //query using parent user too
+                carModeComponentInfoForParentUser = getCurrentCarModeComponent(
+                        parentUser);
+            }
+
             if (carModeComponentInfo != null &&
                     !carModeComponentInfo.getComponentName().equals(
                             mDefaultDialerCache.getSystemDialerComponent())) {
                 carModeInCall = new InCallServiceBindingConnection(carModeComponentInfo);
+            } else if (carModeComponentInfo == null &&
+                    carModeComponentInfoForParentUser != null &&
+                    !carModeComponentInfoForParentUser.getComponentName().equals(
+                            mDefaultDialerCache.getSystemDialerComponent())) {
+                carModeInCall = new InCallServiceBindingConnection(
+                        carModeComponentInfoForParentUser, parentUser);
+                Log.i(this, "Using car mode component queried using parent handle");
             }
 
             mInCallServiceConnections.put(userFromCall,
@@ -1739,17 +1904,49 @@
 
         IntentFilter packageChangedFilter = new IntentFilter(Intent.ACTION_PACKAGE_CHANGED);
         packageChangedFilter.addDataScheme("package");
-        mContext.registerReceiver(mPackageChangedReceiver, packageChangedFilter);
+        mContext.registerReceiverAsUser(mPackageChangedReceiver, UserHandle.ALL,
+                packageChangedFilter, null, null);
     }
 
     private void updateNonUiInCallServices(Call call) {
         UserHandle userFromCall = getUserFromCall(call);
+        UserHandle parentUser = null;
+
+        UserManager um = mContext.getSystemService(UserManager.class);
+        if(um.isManagedProfile(userFromCall.getIdentifier()))
+        {
+            parentUser = um.getProfileParent(userFromCall);
+        }
+
         List<InCallServiceInfo> nonUIInCallComponents =
                 getInCallServiceComponents(userFromCall, IN_CALL_SERVICE_TYPE_NON_UI);
+        List<InCallServiceInfo> nonUIInCallComponentsForParent = new ArrayList<>();
+        if(parentUser != null)
+        {
+            //also get Non-UI services using parent handle.
+            nonUIInCallComponentsForParent =
+                    getInCallServiceComponents(parentUser, IN_CALL_SERVICE_TYPE_NON_UI);
+
+        }
         List<InCallServiceBindingConnection> nonUIInCalls = new LinkedList<>();
         for (InCallServiceInfo serviceInfo : nonUIInCallComponents) {
             nonUIInCalls.add(new InCallServiceBindingConnection(serviceInfo));
         }
+
+        //add nonUI InCall services queried using parent user (if any)
+        for (InCallServiceInfo serviceInfo : nonUIInCallComponentsForParent) {
+            if (nonUIInCallComponents.contains(serviceInfo)) {
+                //skip dups
+                Log.i(this, "skipped duplicate component found using parent user: "
+                        + serviceInfo.getComponentName());
+            } else {
+                nonUIInCalls.add(new InCallServiceBindingConnection(serviceInfo, parentUser));
+                Log.i(this,
+                        "added component queried using parent user: "
+                                + serviceInfo.getComponentName());
+            }
+        }
+
         List<String> callCompanionApps = mCallsManager
                 .getRoleManagerAdapter().getCallCompanionApps();
         if (callCompanionApps != null && !callCompanionApps.isEmpty()) {
@@ -1816,7 +2013,7 @@
             // Last Resort: Try to bind to the ComponentName given directly.
             Log.e(this, new Exception(), "Package Manager could not find ComponentName: "
                     + componentName + ". Trying to bind anyway.");
-            return new InCallServiceInfo(componentName, false, false, type);
+            return new InCallServiceInfo(componentName, false, false, type, false);
         }
     }
 
@@ -1851,6 +2048,34 @@
         return getInCallServiceComponents(userHandle, packageName,
                 componentName, requestedType, true /* ignoreDisabled */);
     }
+    private boolean canInteractAcrossUsersOrProfiles(ServiceInfo serviceInfo,
+            PackageManager packageManager) {
+        String op = AppOpsManager.permissionToOp("android.permission.INTERACT_ACROSS_PROFILES");
+        String[] uidPackages = packageManager.getPackagesForUid(serviceInfo.applicationInfo.uid);
+
+        boolean hasInteractAcrossProfiles = Arrays.stream(uidPackages).anyMatch(
+                p -> ((packageManager.checkPermission(
+                        Manifest.permission.INTERACT_ACROSS_PROFILES,
+                        p) == PackageManager.PERMISSION_GRANTED)
+                ));
+        boolean hasInteractAcrossUsers = Arrays.stream(uidPackages).anyMatch(
+                p -> ((packageManager.checkPermission(
+                        Manifest.permission.INTERACT_ACROSS_USERS,
+                        p) == PackageManager.PERMISSION_GRANTED)
+                ));
+        boolean hasInteractAcrossProfilesAppOp = Arrays.stream(uidPackages).anyMatch(
+                p -> (AppOpsManager.MODE_ALLOWED == mAppOpsManager.checkOpNoThrow(
+                        op, serviceInfo.applicationInfo.uid, p))
+        );
+        Log.i(this,
+                "packageName:%s INTERACT_ACROSS_USERS:%b INTERACT_ACROSS_PROFILES:%b "
+                        + "INTERACT_ACROSS_PROFILES_APPOP:%b",
+                uidPackages[0], hasInteractAcrossUsers, hasInteractAcrossProfiles,
+                hasInteractAcrossProfilesAppOp);
+
+        return (hasInteractAcrossUsers || hasInteractAcrossProfiles
+                || hasInteractAcrossProfilesAppOp);
+    }
 
     private List<InCallServiceInfo> getInCallServiceComponents(UserHandle userHandle,
             String packageName, ComponentName componentName,
@@ -1864,11 +2089,16 @@
         if (componentName != null) {
             serviceIntent.setComponent(componentName);
         }
+        Log.i(this,
+                "getComponents, pkgname: " + packageName + " comp: " + componentName + " userid: "
+                        + userHandle.getIdentifier() + " requestedType: " + requestedType);
         PackageManager packageManager = mContext.getPackageManager();
         Context userContext = mContext.createContextAsUser(userHandle,
                 0 /* flags */);
         PackageManager userPackageManager = userContext != null ?
                 userContext.getPackageManager() : packageManager;
+
+
         for (ResolveInfo entry : packageManager.queryIntentServicesAsUser(
                 serviceIntent,
                 PackageManager.GET_META_DATA | PackageManager.MATCH_DISABLED_COMPONENTS,
@@ -1885,6 +2115,10 @@
 
                 int currentType = getInCallServiceType(userHandle,
                         entry.serviceInfo, packageManager, packageName);
+
+                boolean hasInteractAcrossUserOrProfilePerm = canInteractAcrossUsersOrProfiles(
+                        entry.serviceInfo, packageManager);
+
                 ComponentName foundComponentName =
                         new ComponentName(serviceInfo.packageName, serviceInfo.name);
                 if (requestedType == IN_CALL_SERVICE_TYPE_NON_UI) {
@@ -1900,9 +2134,16 @@
                     isRequestedType = requestedType == currentType;
                 }
 
+                Log.i(this,
+                        "found:%s isRequestedtype:%b isEnabled:%b ignoreDisabled:%b "
+                                + "hasCrossProfilePerm:%b",
+                        foundComponentName, isRequestedType, isEnabled, ignoreDisabled,
+                        hasInteractAcrossUserOrProfilePerm);
+
                 if ((!ignoreDisabled || isEnabled) && isRequestedType) {
                     retval.add(new InCallServiceInfo(foundComponentName, isExternalCallsSupported,
-                            isSelfManageCallsSupported, requestedType));
+                            isSelfManageCallsSupported, requestedType,
+                            hasInteractAcrossUserOrProfilePerm));
                 }
             }
         }
@@ -2436,19 +2677,48 @@
         Log.i(this, "updateCarModeForConnections: car mode apps: %s",
                 mCarModeTracker.getCarModeApps().stream().collect(Collectors.joining(", ")));
 
-        if (mInCallServiceConnections.containsKey(mCallsManager.getCurrentUserHandle())) {
-            CarSwappingInCallServiceConnection inCallServiceConnection = mInCallServiceConnections.
-                    get(mCallsManager.getCurrentUserHandle());
-            if (shouldUseCarModeUI()) {
-                Log.i(this, "updateCarModeForConnections: potentially update car mode app.");
-                inCallServiceConnection.changeCarModeApp(mCarModeTracker.getCurrentCarModePackage(),
-                        mCallsManager.getCurrentUserHandle());
-            } else {
-                if (inCallServiceConnection.isCarMode()) {
-                    Log.i(this, "updateCarModeForConnections: car mode no longer "
-                            + "applicable; disabling");
-                    inCallServiceConnection.disableCarMode();
-                }
+        UserManager um = mContext.getSystemService(UserManager.class);
+        UserHandle currentUser = mCallsManager.getCurrentUserHandle();
+        UserHandle childUser = findChildManagedProfileUser(currentUser, um);
+
+        CarSwappingInCallServiceConnection inCallServiceConnectionForCurrentUser = null;
+        CarSwappingInCallServiceConnection inCallServiceConnectionForChildUser = null;
+
+        Log.i(this, "update carmode current:%s parent:%s", currentUser, childUser);
+        if (mInCallServiceConnections.containsKey(currentUser)) {
+            inCallServiceConnectionForCurrentUser = mInCallServiceConnections.
+                    get(currentUser);
+        }
+        if (childUser != null && mInCallServiceConnections.containsKey(childUser)) {
+            inCallServiceConnectionForChildUser = mInCallServiceConnections.
+                    get(childUser);
+        }
+
+        if (shouldUseCarModeUI()) {
+            Log.i(this, "updateCarModeForConnections: potentially update car mode app.");
+            //always pass current user to changeCarMode. That will ultimately be used for bindAsUser
+            if (inCallServiceConnectionForCurrentUser != null) {
+                inCallServiceConnectionForCurrentUser.changeCarModeApp(
+                        mCarModeTracker.getCurrentCarModePackage(),
+                        currentUser);
+            }
+            if (inCallServiceConnectionForChildUser != null) {
+                inCallServiceConnectionForChildUser.changeCarModeApp(
+                        mCarModeTracker.getCurrentCarModePackage(),
+                        currentUser);
+            }
+        } else {
+            if (inCallServiceConnectionForCurrentUser != null
+                    && inCallServiceConnectionForCurrentUser.isCarMode()) {
+                Log.i(this, "updateCarModeForConnections: car mode no longer "
+                        + "applicable for current user; disabling");
+                inCallServiceConnectionForCurrentUser.disableCarMode();
+            }
+            if (inCallServiceConnectionForChildUser != null
+                    && inCallServiceConnectionForChildUser.isCarMode()) {
+                Log.i(this, "updateCarModeForConnections: car mode no longer "
+                        + "applicable for child user; disabling");
+                inCallServiceConnectionForChildUser.disableCarMode();
             }
         }
     }
@@ -2600,12 +2870,16 @@
         if (call == null) {
             return mCallsManager.getCurrentUserHandle();
         } else {
-            UserHandle userFromCall = call.getUserHandleFromTargetPhoneAccount();
+            UserHandle userFromCall = call.getAssociatedUser();
             UserManager userManager = mContext.getSystemService(UserManager.class);
             // Emergency call should never be blocked, so if the user associated with call is in
             // quite mode, use the primary user for the emergency call.
             if ((call.isEmergencyCall() || call.isInECBM())
-                    && userManager.isQuietModeEnabled(userFromCall)) {
+                    && (userManager.isQuietModeEnabled(userFromCall)
+                    // We should also account for secondary/guest users where the profile may not
+                    // necessarily be paused.
+                    || !userManager.isUserAdmin(mCallsManager.getCurrentUserHandle()
+                    .getIdentifier()))) {
                 return mCallsManager.getCurrentUserHandle();
             }
             return userFromCall;
diff --git a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
index 8426d1f..3b402b1 100644
--- a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
+++ b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
@@ -382,14 +382,14 @@
              * broadcasting.
              */
             callRedirectionWithService = callRedirectionProcessor
-                    .canMakeCallRedirectionWithServiceAsUser(mCall.getInitiatingUser());
+                    .canMakeCallRedirectionWithServiceAsUser(mCall.getAssociatedUser());
             if (callRedirectionWithService) {
-                callRedirectionProcessor.performCallRedirection(mCall.getInitiatingUser());
+                callRedirectionProcessor.performCallRedirection(mCall.getAssociatedUser());
             }
         }
 
         if (disposition.sendBroadcast) {
-            UserHandle targetUser = mCall.getInitiatingUser();
+            UserHandle targetUser = mCall.getAssociatedUser();
             Log.i(this, "Sending NewOutgoingCallBroadcast for %s to %s", mCall, targetUser);
             broadcastIntent(mIntent, disposition.number,
                     !disposition.callImmediately && !callRedirectionWithService, targetUser);
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index f5a3450..acf07e3 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -205,6 +205,7 @@
 
         // register context based receiver to clean up orphan phone accounts
         IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MANAGED_PROFILE_REMOVED);
+        intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         mContext.registerReceiver(mManagedProfileReceiver, intentFilter);
 
         read();
@@ -562,10 +563,7 @@
         if (call == null) {
             return null;
         }
-        UserHandle userHandle = call.getInitiatingUser();
-        if (userHandle == null) {
-            userHandle = call.getTargetPhoneAccount().getUserHandle();
-        }
+        UserHandle userHandle = call.getAssociatedUser();
         PhoneAccountHandle targetPhoneAccount = call.getTargetPhoneAccount();
         Log.d(this, "getSimCallManagerFromCall: callId=%s, targetPhac=%s",
                 call.getId(), targetPhoneAccount);
diff --git a/src/com/android/server/telecom/RespondViaSmsManager.java b/src/com/android/server/telecom/RespondViaSmsManager.java
index 8507703..1d42db4 100644
--- a/src/com/android/server/telecom/RespondViaSmsManager.java
+++ b/src/com/android/server/telecom/RespondViaSmsManager.java
@@ -215,8 +215,9 @@
             MessageSentReceiver receiver = new MessageSentReceiver(
                     !TextUtils.isEmpty(contactName) ? contactName : phoneNumber,
                     messageParts.size());
-            context.registerReceiver(receiver, new IntentFilter(ACTION_MESSAGE_SENT),
-                    Context.RECEIVER_NOT_EXPORTED);
+            IntentFilter messageSentFilter = new IntentFilter(ACTION_MESSAGE_SENT);
+            messageSentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+            context.registerReceiver(receiver, messageSentFilter, Context.RECEIVER_NOT_EXPORTED);
             smsManager.sendMultipartTextMessage(phoneNumber, null, messageParts,
                     sentIntents/*sentIntent*/, null /*deliveryIntent*/, context.getOpPackageName(),
                     context.getAttributionTag());
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index 45fb2af..1710604 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -552,7 +552,7 @@
         }
 
         if (mInCallController.doesConnectedDialerSupportRinging(
-                call.getUserHandleFromTargetPhoneAccount())) {
+                call.getAssociatedUser())) {
             Log.addEvent(call, LogUtils.Events.SKIP_RINGING, "Dialer handles");
             return;
         }
@@ -689,10 +689,10 @@
         boolean isTheaterModeOn = mSystemSettingsUtil.isTheaterModeOn(mContext);
         timer.record("isTheaterModeOn");
         boolean letDialerHandleRinging = mInCallController.doesConnectedDialerSupportRinging(
-                call.getUserHandleFromTargetPhoneAccount());
+                call.getAssociatedUser());
         timer.record("letDialerHandleRinging");
         boolean isWorkProfileInQuietMode =
-                isProfileInQuietMode(call.getUserHandleFromTargetPhoneAccount());
+                isProfileInQuietMode(call.getAssociatedUser());
         timer.record("isWorkProfileInQuietMode");
 
         Log.i(this, "startRinging timings: " + timer);
diff --git a/src/com/android/server/telecom/RingtoneFactory.java b/src/com/android/server/telecom/RingtoneFactory.java
index 309c86e..6bcfb4c 100644
--- a/src/com/android/server/telecom/RingtoneFactory.java
+++ b/src/com/android/server/telecom/RingtoneFactory.java
@@ -75,7 +75,7 @@
         // or the default ringtone of the receiving user.
         Context userContext = isWorkContact(incomingCall) ?
                 getWorkProfileContextForUser(mCallsManager.getCurrentUserHandle()) :
-                getContextForUserHandle(incomingCall.getUserHandleFromTargetPhoneAccount());
+                getContextForUserHandle(incomingCall.getAssociatedUser());
         Uri ringtoneUri = incomingCall.getRingtone();
         Ringtone ringtone = null;
 
diff --git a/src/com/android/server/telecom/SystemStateHelper.java b/src/com/android/server/telecom/SystemStateHelper.java
index dd978c2..5eed1ac 100644
--- a/src/com/android/server/telecom/SystemStateHelper.java
+++ b/src/com/android/server/telecom/SystemStateHelper.java
@@ -146,9 +146,11 @@
         IntentFilter intentFilter1 = new IntentFilter(
                 UiModeManager.ACTION_ENTER_CAR_MODE_PRIORITIZED);
         intentFilter1.addAction(UiModeManager.ACTION_EXIT_CAR_MODE_PRIORITIZED);
+        intentFilter1.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
 
         IntentFilter intentFilter2 = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
         intentFilter2.addDataScheme("package");
+        intentFilter2.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         mContext.registerReceiver(mBroadcastReceiver, intentFilter1);
         mContext.registerReceiver(mBroadcastReceiver, intentFilter2);
         Log.i(this, "Registering broadcast receiver: %s", intentFilter1);
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index ca42b57..f33b185 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -2173,7 +2173,7 @@
                                     || call.getState() == CallState.DISCONNECTING) {
                                 mCallsManager.markCallAsRemoved(call);
                             }
-                            userHandles.add(call.getUserHandleFromTargetPhoneAccount());
+                            userHandles.add(call.getAssociatedUser());
                         }
                         for (UserHandle userHandle : userHandles) {
                             mCallsManager.getInCallController().unbindFromServices(userHandle);
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index d3ca0b7..67bb81f 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -116,6 +116,11 @@
                 .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_MARK, null);
         DIALER_SECRET_CODE_FILTER
                 .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_MENU, null);
+
+        USER_SWITCHED_FILTER.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        USER_STARTING_FILTER.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        BOOT_COMPLETE_FILTER.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        DIALER_SECRET_CODE_FILTER.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
     }
 
     private static TelecomSystem INSTANCE = null;
diff --git a/src/com/android/server/telecom/TransactionalServiceRepository.java b/src/com/android/server/telecom/TransactionalServiceRepository.java
index f84b934..15278e1 100644
--- a/src/com/android/server/telecom/TransactionalServiceRepository.java
+++ b/src/com/android/server/telecom/TransactionalServiceRepository.java
@@ -16,6 +16,7 @@
 
 package com.android.server.telecom;
 
+import android.telecom.Log;
 import android.telecom.PhoneAccountHandle;
 
 import com.android.internal.telecom.ICallEventCallback;
@@ -28,8 +29,8 @@
  * more calls.
  */
 public class TransactionalServiceRepository {
-
-    private static final Map<PhoneAccountHandle, TransactionalServiceWrapper> lookupTable =
+    private static final String TAG = TransactionalServiceRepository.class.getSimpleName();
+    private static final Map<PhoneAccountHandle, TransactionalServiceWrapper> mServiceLookupTable =
             new HashMap<>();
 
     public TransactionalServiceRepository() {
@@ -38,12 +39,15 @@
     public TransactionalServiceWrapper addNewCallForTransactionalServiceWrapper
             (PhoneAccountHandle phoneAccountHandle, ICallEventCallback callEventCallback,
                     CallsManager callsManager, Call call) {
-
-        TransactionalServiceWrapper service = null;
+        TransactionalServiceWrapper service;
+        // Only create a new TransactionalServiceWrapper if this is the first call for a package.
+        // Otherwise, get the existing TSW and add the new call to the service.
         if (!hasExistingServiceWrapper(phoneAccountHandle)) {
+            Log.d(TAG, "creating a new TSW; handle=[%s]", phoneAccountHandle);
             service = new TransactionalServiceWrapper(callEventCallback,
                     callsManager, phoneAccountHandle, call, this);
         } else {
+            Log.d(TAG, "add a new call to an existing TSW; handle=[%s]", phoneAccountHandle);
             service = getTransactionalServiceWrapper(phoneAccountHandle);
             if (service == null) {
                 throw new IllegalStateException("service is null");
@@ -52,25 +56,25 @@
             }
         }
 
-        lookupTable.put(phoneAccountHandle, service);
+        mServiceLookupTable.put(phoneAccountHandle, service);
 
         return service;
     }
 
     public TransactionalServiceWrapper getTransactionalServiceWrapper(PhoneAccountHandle pah) {
-        return lookupTable.get(pah);
+        return mServiceLookupTable.get(pah);
     }
 
     public boolean hasExistingServiceWrapper(PhoneAccountHandle pah) {
-        return lookupTable.containsKey(pah);
+        return mServiceLookupTable.containsKey(pah);
     }
 
     public boolean removeServiceWrapper(PhoneAccountHandle pah) {
+        Log.i(TAG, "removeServiceWrapper: for phoneAccountHandle=[%s]", pah);
         if (!hasExistingServiceWrapper(pah)) {
             return false;
         }
-        lookupTable.remove(pah);
+        mServiceLookupTable.remove(pah);
         return true;
     }
-
 }
diff --git a/src/com/android/server/telecom/TransactionalServiceWrapper.java b/src/com/android/server/telecom/TransactionalServiceWrapper.java
index ec95f39..25aaad7 100644
--- a/src/com/android/server/telecom/TransactionalServiceWrapper.java
+++ b/src/com/android/server/telecom/TransactionalServiceWrapper.java
@@ -51,17 +51,17 @@
 import com.android.server.telecom.voip.VoipCallTransactionResult;
 
 import java.util.ArrayList;
-import java.util.Hashtable;
 import java.util.List;
 import java.util.Locale;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * Implements {@link android.telecom.CallEventCallback} and {@link android.telecom.CallControl}
  * on a per-client basis which is tied to a {@link PhoneAccountHandle}
  */
 public class TransactionalServiceWrapper implements
-        ConnectionServiceFocusManager.ConnectionServiceFocus, IBinder.DeathRecipient {
+        ConnectionServiceFocusManager.ConnectionServiceFocus {
     private static final String TAG = TransactionalServiceWrapper.class.getSimpleName();
 
     // CallControl : Client (ex. voip app) --> Telecom
@@ -84,13 +84,25 @@
     private final TransactionalServiceRepository mRepository;
     private ConnectionServiceFocusManager.ConnectionServiceFocusListener mConnSvrFocusListener;
     // init when constructor is called
-    private final Hashtable<String, Call> mTrackedCalls = new Hashtable<>();
+    private final ConcurrentHashMap<String, Call> mTrackedCalls = new ConcurrentHashMap<>();
     private final TelecomSystem.SyncRoot mLock;
     private final String mPackageName;
     // needs to be non-final for testing
     private TransactionManager mTransactionManager;
     private CallStreamingController mStreamingController;
 
+
+    // Each TransactionalServiceWrapper should have their own Binder.DeathRecipient to clean up
+    // any calls in the event the application crashes or is force stopped.
+    private final IBinder.DeathRecipient mAppDeathListener = new IBinder.DeathRecipient() {
+        @Override
+        public void binderDied() {
+            Log.i(TAG, "binderDied: for package=[%s]; cleaning calls", mPackageName);
+            cleanupTransactionalServiceWrapper();
+            mICallEventCallback.asBinder().unlinkToDeath(this, 0);
+        }
+    };
+
     public TransactionalServiceWrapper(ICallEventCallback callEventCallback,
             CallsManager callsManager, PhoneAccountHandle phoneAccountHandle, Call call,
             TransactionalServiceRepository repo) {
@@ -105,6 +117,7 @@
         mTransactionManager = TransactionManager.getInstance();
         mStreamingController = mCallsManager.getCallStreamingController();
         mLock = mCallsManager.getLock();
+        setDeathRecipient(callEventCallback);
     }
 
     @VisibleForTesting
@@ -128,12 +141,6 @@
         }
     }
 
-    public Call getCallById(String callId) {
-        synchronized (mLock) {
-            return mTrackedCalls.get(callId);
-        }
-    }
-
     @VisibleForTesting
     public boolean untrackCall(Call call) {
         Call removedCall = null;
@@ -158,23 +165,12 @@
         return callCount;
     }
 
-    @Override
-    public void binderDied() {
-        // remove all tacked calls from CallsManager && frameworks side
-        for (String id : mTrackedCalls.keySet()) {
-            Call call = mTrackedCalls.get(id);
-            mCallsManager.markCallAsDisconnected(call, new DisconnectCause(DisconnectCause.ERROR));
-            mCallsManager.removeCall(call);
-            // remove calls from Frameworks side
-            if (mICallEventCallback != null) {
-                try {
-                    mICallEventCallback.removeCallFromTransactionalServiceWrapper(call.getId());
-                } catch (RemoteException e) {
-                    // pass
-                }
-            }
+    public void cleanupTransactionalServiceWrapper() {
+        for (Call call : mTrackedCalls.values()) {
+            mCallsManager.markCallAsDisconnected(call,
+                    new DisconnectCause(DisconnectCause.ERROR, "process died"));
+            mCallsManager.removeCall(call); // This will clear mTrackedCalls && ClientTWS
         }
-        mTrackedCalls.clear();
     }
 
     /***
@@ -262,7 +258,8 @@
                                 new HoldCallTransaction(mCallsManager, call), callback);
                         break;
                     case START_STREAMING:
-                        addTransactionsToManager(createStartStreamingTransaction(call), callback);
+                        addTransactionsToManager(mStreamingController.getStartStreamingTransaction(mCallsManager,
+                                TransactionalServiceWrapper.this, call, mLock), callback);
                         break;
                 }
             } else {
@@ -336,7 +333,7 @@
         }
     };
 
-    private void addTransactionsToManager(VoipCallTransaction transaction,
+    public void addTransactionsToManager(VoipCallTransaction transaction,
             ResultReceiver callback) {
         Log.d(TAG, "addTransactionsToManager");
 
@@ -555,10 +552,10 @@
             try {
                 // remove the call from frameworks wrapper (client side)
                 mICallEventCallback.removeCallFromTransactionalServiceWrapper(call.getId());
-                // remove the call from this class/wrapper (server side)
-                untrackCall(call);
             } catch (RemoteException e) {
             }
+            // remove the call from this class/wrapper (server side)
+            untrackCall(call);
         }
     }
 
@@ -604,6 +601,15 @@
         return new SerialTransaction(transactions, mLock);
     }
 
+    private void setDeathRecipient(ICallEventCallback callEventCallback) {
+        try {
+            callEventCallback.asBinder().linkToDeath(mAppDeathListener, 0);
+        } catch (Exception e) {
+            Log.w(TAG, "setDeathRecipient: hit exception=[%s] trying to link binder to death",
+                    e.toString());
+        }
+    }
+
     /***
      *********************************************************************************************
      **                    FocusManager                                                       **
@@ -642,49 +648,11 @@
      *********************************************************************************************
      */
 
-    private SerialTransaction createStartStreamingTransaction(Call call) {
-        // start streaming transaction flow:
-        //     make sure there's no ongoing streaming call --> bind to EXO
-        //                                                 `-> change audio mode
-        // create list for multiple transactions
-        List<VoipCallTransaction> transactions = new ArrayList<>();
-
-        // add t1. make sure no ongoing streaming call
-        transactions.add(new CallStreamingController.QueryCallStreamingTransaction(mCallsManager));
-
-        // create list for parallel transactions
-        List<VoipCallTransaction> subTransactions = new ArrayList<>();
-        // add t2.1 bind to call streaming service
-        subTransactions.add(mStreamingController.getCallStreamingServiceTransaction(
-                mCallsManager.getContext(), this, call));
-        // add t2.2 audio route operations
-        subTransactions.add(new CallStreamingController.AudioInterceptionTransaction(call,
-                true, mLock));
-
-        // add t2
-        transactions.add(new ParallelTransaction(subTransactions, mLock));
-        // send off to Transaction Manager to process
-        return new SerialTransaction(transactions, mLock);
-    }
-
-    private VoipCallTransaction createStopStreamingTransaction(Call call) {
-        // TODO: implement this
-        // Stop streaming transaction flow:
-        List<VoipCallTransaction> transactions = new ArrayList<>();
-
-        // 1. unbind to call streaming service
-        transactions.add(mStreamingController.getUnbindStreamingServiceTransaction());
-        // 2. audio route operations
-        transactions.add(new CallStreamingController.AudioInterceptionTransaction(call,
-                false, mLock));
-        return new ParallelTransaction(transactions, mLock);
-    }
-
-
     public void stopCallStreaming(Call call) {
         Log.i(this, "stopCallStreaming; callid=%s", call.getId());
         if (call != null && call.isStreaming()) {
-            VoipCallTransaction stopStreamingTransaction = createStopStreamingTransaction(call);
+            VoipCallTransaction stopStreamingTransaction = mStreamingController
+                    .getStopStreamingTransaction(call, mLock);
             addTransactionsToManager(stopStreamingTransaction, new ResultReceiver(null));
         }
     }
diff --git a/src/com/android/server/telecom/TtyManager.java b/src/com/android/server/telecom/TtyManager.java
index 10e3348..53e917d 100644
--- a/src/com/android/server/telecom/TtyManager.java
+++ b/src/com/android/server/telecom/TtyManager.java
@@ -50,6 +50,7 @@
 
         IntentFilter intentFilter = new IntentFilter(
                 TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED);
+        intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         mContext.registerReceiver(mReceiver, intentFilter,
                 android.Manifest.permission.MODIFY_PHONE_STATE,
                 null, Context.RECEIVER_EXPORTED);
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
index e5fe971..20af7b5 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
@@ -46,6 +46,7 @@
         INTENT_FILTER.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED);
         INTENT_FILTER.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
         INTENT_FILTER.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
+        INTENT_FILTER.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
     }
 
     // If not in a call, BSR won't listen to the Bluetooth stack's HFP on/off messages, since
diff --git a/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java b/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java
index f542fa2..f07c0aa 100644
--- a/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java
+++ b/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java
@@ -319,7 +319,7 @@
         CallScreeningServiceConnection connection = new CallScreeningServiceConnection(
                 resultFuture);
         if (!CallScreeningServiceHelper.bindCallScreeningService(mContext,
-                mCall.getUserHandleFromTargetPhoneAccount(), mPackageName, connection)) {
+                mCall.getAssociatedUser(), mPackageName, connection)) {
             Log.i(this, "Call screening service binding failed.");
             resultFuture.complete(mPriorStageResult);
         } else {
diff --git a/src/com/android/server/telecom/settings/BlockedNumbersActivity.java b/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
index 7345a67..5fa5f06 100644
--- a/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
+++ b/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
@@ -154,8 +154,10 @@
                 updateButterBar();
             }
         };
-        registerReceiver(mBlockingStatusReceiver, new IntentFilter(
-                BlockedNumberContract.SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED),
+        IntentFilter blockStatusIntentFilter = new IntentFilter(
+                BlockedNumberContract.SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED);
+        blockStatusIntentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        registerReceiver(mBlockingStatusReceiver, blockStatusIntentFilter,
                 Context.RECEIVER_EXPORTED);
 
         getLoaderManager().initLoader(0, null, this);
diff --git a/src/com/android/server/telecom/ui/AudioProcessingNotification.java b/src/com/android/server/telecom/ui/AudioProcessingNotification.java
index e38178e..952bee8 100644
--- a/src/com/android/server/telecom/ui/AudioProcessingNotification.java
+++ b/src/com/android/server/telecom/ui/AudioProcessingNotification.java
@@ -54,7 +54,7 @@
         } else if (oldState == CallState.AUDIO_PROCESSING
                 && newState != CallState.AUDIO_PROCESSING) {
             cancelAudioProcessingNotification(
-                    call.getUserHandleFromTargetPhoneAccount());
+                    call.getAssociatedUser());
         }
     }
 
@@ -69,7 +69,7 @@
     public void onCallRemoved(Call call) {
         if (call == mCallInAudioProcessing) {
             cancelAudioProcessingNotification(
-                    call.getUserHandleFromTargetPhoneAccount());
+                    call.getAssociatedUser());
         }
     }
 
@@ -80,7 +80,7 @@
      */
     private void showAudioProcessingNotification(Call call) {
         Log.i(this, "showAudioProcessingNotification for user = %s",
-                call.getUserHandleFromTargetPhoneAccount());
+                call.getAssociatedUser());
         mCallInAudioProcessing = call;
 
         Notification.Builder builder = new Notification.Builder(mContext,
@@ -97,7 +97,7 @@
         Notification notification = builder.build();
 
         mNotificationManager.notifyAsUser(NOTIFICATION_TAG, AUDIO_PROCESSING_NOTIFICATION_ID,
-                notification, mCallInAudioProcessing.getUserHandleFromTargetPhoneAccount());
+                notification, mCallInAudioProcessing.getAssociatedUser());
     }
 
     /** Cancels the audio processing notification. */
diff --git a/src/com/android/server/telecom/ui/CallStreamingNotification.java b/src/com/android/server/telecom/ui/CallStreamingNotification.java
index 3f09bb1..8414047 100644
--- a/src/com/android/server/telecom/ui/CallStreamingNotification.java
+++ b/src/com/android/server/telecom/ui/CallStreamingNotification.java
@@ -157,7 +157,7 @@
                 Log.e(this, e, "enqueueStreamingNotification: Couldn't build avatar icon");
             }
             showStreamingNotification(call.getId(),
-                    call.getUserHandleFromTargetPhoneAccount(), call.getCallerDisplayName(),
+                    call.getAssociatedUser(), call.getCallerDisplayName(),
                     call.getHandle(), contactPhotoIcon,
                     call.getTargetPhoneAccount().getComponentName().getPackageName(),
                     call.getConnectTimeMillis());
diff --git a/src/com/android/server/telecom/ui/DisconnectedCallNotifier.java b/src/com/android/server/telecom/ui/DisconnectedCallNotifier.java
index 66f9fe4..1604285 100644
--- a/src/com/android/server/telecom/ui/DisconnectedCallNotifier.java
+++ b/src/com/android/server/telecom/ui/DisconnectedCallNotifier.java
@@ -143,8 +143,7 @@
                 DisconnectCause.REASON_EMERGENCY_CALL_PLACED.equals(cause.getReason())) {
             // Clear any existing notification.
             clearNotification(mCallsManager.getCurrentUserHandle());
-            UserHandle userHandle = call.getTargetPhoneAccount() != null ?
-                    call.getTargetPhoneAccount().getUserHandle() : call.getInitiatingUser();
+            UserHandle userHandle = call.getAssociatedUser();
             // As a last resort, use the current user to display the notification.
             if (userHandle == null) userHandle = mCallsManager.getCurrentUserHandle();
             mPendingCallNotification = new CallInfo(userHandle, call.getHandle(),
diff --git a/src/com/android/server/telecom/ui/IncomingCallNotifier.java b/src/com/android/server/telecom/ui/IncomingCallNotifier.java
index 3b188d4..d419163 100644
--- a/src/com/android/server/telecom/ui/IncomingCallNotifier.java
+++ b/src/com/android/server/telecom/ui/IncomingCallNotifier.java
@@ -168,19 +168,19 @@
             } else if (hadIncomingCall && !hasIncomingCall) {
                 previousIncomingCall.removeListener(mCallListener);
                 hideIncomingCallNotification(
-                        previousIncomingCall.getUserHandleFromTargetPhoneAccount());
+                        previousIncomingCall.getAssociatedUser());
             }
         }
     }
 
     private void showIncomingCallNotification(Call call) {
         Log.i(this, "showIncomingCallNotification showCall = %s for user = %s",
-                call, call.getUserHandleFromTargetPhoneAccount());
+                call, call.getAssociatedUser());
 
         Notification.Builder builder = getNotificationBuilder(call,
                 mCallsManagerProxy.getActiveCall());
         mNotificationManager.notifyAsUser(NOTIFICATION_TAG, NOTIFICATION_INCOMING_CALL,
-                builder.build(), call.getUserHandleFromTargetPhoneAccount());
+                builder.build(), call.getAssociatedUser());
     }
 
     private void hideIncomingCallNotification(UserHandle userHandle) {
diff --git a/src/com/android/server/telecom/ui/NotificationChannelManager.java b/src/com/android/server/telecom/ui/NotificationChannelManager.java
index a0baa03..b3cb2c3 100644
--- a/src/com/android/server/telecom/ui/NotificationChannelManager.java
+++ b/src/com/android/server/telecom/ui/NotificationChannelManager.java
@@ -51,8 +51,9 @@
     };
 
     public void createChannels(Context context) {
-        context.registerReceiver(mLocaleChangeReceiver,
-                new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
+        IntentFilter localeChangedfilter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
+        localeChangedfilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        context.registerReceiver(mLocaleChangeReceiver, localeChangedfilter);
 
         createOrUpdateAll(context);
     }
diff --git a/src/com/android/server/telecom/voip/SerialTransaction.java b/src/com/android/server/telecom/voip/SerialTransaction.java
index 5d5d1f3..b35b471 100644
--- a/src/com/android/server/telecom/voip/SerialTransaction.java
+++ b/src/com/android/server/telecom/voip/SerialTransaction.java
@@ -60,6 +60,7 @@
                         public void onTransactionCompleted(VoipCallTransactionResult result,
                                 String transactionName) {
                             if (result.getResult() != VoipCallTransactionResult.RESULT_SUCCEED) {
+                                handleTransactionFailure();
                                 CompletableFuture.completedFuture(null).thenApplyAsync(
                                         (x) -> {
                                             VoipCallTransactionResult mainResult =
@@ -88,6 +89,7 @@
 
                         @Override
                         public void onTransactionTimeout(String transactionName) {
+                            handleTransactionFailure();
                             CompletableFuture.completedFuture(null).thenApplyAsync(
                                     (x) -> {
                                         VoipCallTransactionResult mainResult =
@@ -111,4 +113,6 @@
             scheduleTransaction();
         }
     }
+
+    public void handleTransactionFailure() {}
 }
diff --git a/src/com/android/server/telecom/voip/VoipCallMonitor.java b/src/com/android/server/telecom/voip/VoipCallMonitor.java
index 9254395..3779a6d 100644
--- a/src/com/android/server/telecom/voip/VoipCallMonitor.java
+++ b/src/com/android/server/telecom/voip/VoipCallMonitor.java
@@ -36,6 +36,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
 import com.android.server.telecom.Call;
+
 import com.android.server.telecom.CallsManagerListenerBase;
 import com.android.server.telecom.LogUtils;
 import com.android.server.telecom.LoggedHandlerExecutor;
@@ -46,6 +47,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 
@@ -89,13 +91,21 @@
                         boolean sbnMatched = false;
                         for (Call call : mNotificationPendingCalls) {
                             if (info.matchesCall(call)) {
+                                Log.i(this, "onNotificationPosted: found a pending "
+                                                + "callId=[%s] for the call notification w/ "
+                                                + "id=[%s]",
+                                        call.getId(), sbn.getId());
                                 mNotificationPendingCalls.remove(call);
                                 mNotificationInfoToCallMap.put(info, call);
                                 sbnMatched = true;
                                 break;
                             }
                         }
-                        if (!sbnMatched) {
+                        if (!sbnMatched &&
+                                !mCachedNotifications.contains(info) /* don't re-add if update */) {
+                            Log.i(this, "onNotificationPosted: could not find a"
+                                            + "call for the call notification w/ id=[%s]",
+                                    sbn.getId());
                             // notification may post before we started to monitor the call, cache
                             // this notification and try to match it later with new added call.
                             mCachedNotifications.add(info);
@@ -154,7 +164,6 @@
             Set<Call> callList = mAccountHandleToCallMap.computeIfAbsent(phoneAccountHandle,
                     k -> new HashSet<>());
             callList.add(call);
-
             CompletableFuture.completedFuture(null).thenComposeAsync(
                     (x) -> {
                         startFGSDelegation(call.getCallingPackageIdentity().mCallingPackagePid,
@@ -223,11 +232,15 @@
             Log.i(this, "stopFGSDelegation of call %s", call);
             PhoneAccountHandle handle = call.getTargetPhoneAccount();
             Set<Call> calls = mAccountHandleToCallMap.get(handle);
+
+            // Every call for the package that is losing foreground service delegation should be
+            // removed from tracking maps/contains in this class
             if (calls != null) {
                 for (Call c : calls) {
-                    stopMonitorWorks(c);
+                    stopMonitorWorks(c); // remove the call from tacking in this class
                 }
             }
+
             mAccountHandleToCallMap.remove(handle);
 
             if (mActivityManagerInternal != null) {
@@ -253,6 +266,8 @@
             boolean sbnMatched = false;
             for (NotificationInfo info : mCachedNotifications) {
                 if (info.matchesCall(call)) {
+                    Log.i(this, "startMonitorNotification: found a cached call "
+                            + "notification for call=[%s]", call);
                     mCachedNotifications.remove(info);
                     mNotificationInfoToCallMap.put(info, call);
                     sbnMatched = true;
@@ -261,6 +276,8 @@
             }
             if (!sbnMatched) {
                 // Only continue to
+                Log.i(this, "startMonitorNotification: could not find a call"
+                        + " notification for the call=[%s];", call);
                 mNotificationPendingCalls.add(call);
                 CompletableFuture<Void> future = new CompletableFuture<>();
                 mHandler.postDelayed(() -> future.complete(null), 5000L);
@@ -288,12 +305,7 @@
         mActivityManagerInternal = ami;
     }
 
-    @VisibleForTesting
-    public void setNotificationListenerService(NotificationListenerService listener) {
-        mNotificationListener = listener;
-    }
-
-    private class NotificationInfo {
+    private static class NotificationInfo extends Object {
         private String mPackageName;
         private UserHandle mUserHandle;
 
@@ -305,8 +317,49 @@
         boolean matchesCall(Call call) {
             PhoneAccountHandle accountHandle = call.getTargetPhoneAccount();
             return mPackageName != null && mPackageName.equals(
-                   accountHandle.getComponentName().getPackageName())
+                    accountHandle.getComponentName().getPackageName())
                     && mUserHandle != null && mUserHandle.equals(accountHandle.getUserHandle());
         }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof NotificationInfo)) {
+                return false;
+            }
+            NotificationInfo that = (NotificationInfo) obj;
+            return Objects.equals(this.mPackageName, that.mPackageName)
+                    && Objects.equals(this.mUserHandle, that.mUserHandle);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mPackageName, mUserHandle);
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("{ NotificationInfo: [mPackageName: ")
+                    .append(mPackageName)
+                    .append("], [mUserHandle=")
+                    .append(mUserHandle)
+                    .append("]  }");
+            return sb.toString();
+        }
+    }
+
+    @VisibleForTesting
+    public void postNotification(StatusBarNotification statusBarNotification) {
+        mNotificationListener.onNotificationPosted(statusBarNotification);
+    }
+
+    @VisibleForTesting
+    public void removeNotification(StatusBarNotification statusBarNotification) {
+        mNotificationListener.onNotificationRemoved(statusBarNotification);
+    }
+
+    @VisibleForTesting
+    public Set<Call> getCallsForHandle(PhoneAccountHandle handle){
+        return mAccountHandleToCallMap.get(handle);
     }
 }
diff --git a/testapps/transactionalVoipApp/res/layout/in_call_activity.xml b/testapps/transactionalVoipApp/res/layout/in_call_activity.xml
index 54d467e..a92a99b 100644
--- a/testapps/transactionalVoipApp/res/layout/in_call_activity.xml
+++ b/testapps/transactionalVoipApp/res/layout/in_call_activity.xml
@@ -29,6 +29,13 @@
     />
 
     <Button
+        android:id="@+id/updateCallStyleNotification"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/update_notification"
+    />
+
+    <Button
         android:id="@+id/answer_button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
@@ -58,6 +65,12 @@
         android:layout_height="wrap_content"
         android:text="@string/start_stream"/>
 
+    <Button
+        android:id="@+id/crash_app"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/crash_app"/>
+
     <LinearLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
diff --git a/testapps/transactionalVoipApp/res/values-af/strings.xml b/testapps/transactionalVoipApp/res/values-af/strings.xml
index 78abd1b..bf7ad33 100644
--- a/testapps/transactionalVoipApp/res/values-af/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-af/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Luidspreker"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"begin stroom"</string>
+    <string name="crash_app" msgid="2548690390730057704">"gooi uitsondering"</string>
+    <string name="update_notification" msgid="8677916482672588779">"dateer kennisgewing aan voortdurende oproepstyl op"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-am/strings.xml b/testapps/transactionalVoipApp/res/values-am/strings.xml
index 2766bf8..120a9b9 100644
--- a/testapps/transactionalVoipApp/res/values-am/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-am/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"ድምጽ ማውጫ"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ብሉቱዝ"</string>
     <string name="start_stream" msgid="3567634786280097431">"ዥረት ይጀምሩ"</string>
+    <string name="crash_app" msgid="2548690390730057704">"ለየት ያለ ነገርን ይጣሉ"</string>
+    <string name="update_notification" msgid="8677916482672588779">"በመካሄድ ላይ ላለ ጥሪ ቅጥ ማሳወቂያ ያዘምኑ"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-ar/strings.xml b/testapps/transactionalVoipApp/res/values-ar/strings.xml
index 8a42e30..d2c1464 100644
--- a/testapps/transactionalVoipApp/res/values-ar/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-ar/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"مكبّر الصوت"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"البلوتوث"</string>
     <string name="start_stream" msgid="3567634786280097431">"بدء البث"</string>
+    <string name="crash_app" msgid="2548690390730057704">"طرح استثناء"</string>
+    <string name="update_notification" msgid="8677916482672588779">"إشعار التعديل إلى نمط المكالمات الجارية"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-as/strings.xml b/testapps/transactionalVoipApp/res/values-as/strings.xml
index 56014c4..c48ac0e 100644
--- a/testapps/transactionalVoipApp/res/values-as/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-as/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"স্পীকাৰ"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ব্লুটুথ"</string>
     <string name="start_stream" msgid="3567634786280097431">"ষ্ট্ৰীম কৰিবলৈ আৰম্ভ কৰক"</string>
+    <string name="crash_app" msgid="2548690390730057704">"থ্ৰ’ এক্সচেপশ্বন"</string>
+    <string name="update_notification" msgid="8677916482672588779">"চলিত কলৰ শৈলী সম্পৰ্কে আপডে’ট দিয়া জাননী"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-az/strings.xml b/testapps/transactionalVoipApp/res/values-az/strings.xml
index 14af0ab..75d8278 100644
--- a/testapps/transactionalVoipApp/res/values-az/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-az/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Dinamik"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"yayıma başlayın"</string>
+    <string name="crash_app" msgid="2548690390730057704">"istisna yaradın"</string>
+    <string name="update_notification" msgid="8677916482672588779">"bildirişi davam edən zəng üslubuna yeniləyin"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-b+sr+Latn/strings.xml b/testapps/transactionalVoipApp/res/values-b+sr+Latn/strings.xml
index 3c4019c..f824910 100644
--- a/testapps/transactionalVoipApp/res/values-b+sr+Latn/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-b+sr+Latn/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Zvučnik"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"počnite da strimujete"</string>
+    <string name="crash_app" msgid="2548690390730057704">"izbaciti izuzetak"</string>
+    <string name="update_notification" msgid="8677916482672588779">"ažurirajte obaveštenje na stil aktuelnog poziva"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-be/strings.xml b/testapps/transactionalVoipApp/res/values-be/strings.xml
index 9decf62..36d558e 100644
--- a/testapps/transactionalVoipApp/res/values-be/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-be/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Дынамік"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"пачаць перадачу плынню"</string>
+    <string name="crash_app" msgid="2548690390730057704">"адправіць паведамленне аб выключэнні"</string>
+    <string name="update_notification" msgid="8677916482672588779">"стыль паведамлення аб абнаўленні для бягучага званка"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-bg/strings.xml b/testapps/transactionalVoipApp/res/values-bg/strings.xml
index 63b55f9..2210400 100644
--- a/testapps/transactionalVoipApp/res/values-bg/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-bg/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Високоговорител"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"започване на поточно предаване"</string>
+    <string name="crash_app" msgid="2548690390730057704">"генериране на изключение"</string>
+    <string name="update_notification" msgid="8677916482672588779">"актуализиране на известието до стила на текущото обаждане"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-bn/strings.xml b/testapps/transactionalVoipApp/res/values-bn/strings.xml
index b03123a..45f13be 100644
--- a/testapps/transactionalVoipApp/res/values-bn/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-bn/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"স্পিকার"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ব্লুটুথ"</string>
     <string name="start_stream" msgid="3567634786280097431">"স্ট্রিমিং শুরু করুন"</string>
+    <string name="crash_app" msgid="2548690390730057704">"এক্সেপশন যোগ করুন"</string>
+    <string name="update_notification" msgid="8677916482672588779">"চালু থাকা কলের স্টাইলে আপডেট সংক্রান্ত বিজ্ঞপ্তি"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-bs/strings.xml b/testapps/transactionalVoipApp/res/values-bs/strings.xml
index e4cbb08..24ffba2 100644
--- a/testapps/transactionalVoipApp/res/values-bs/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-bs/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Zvučnik"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"pokreni prijenos"</string>
+    <string name="crash_app" msgid="2548690390730057704">"izbaci izuzetak"</string>
+    <string name="update_notification" msgid="8677916482672588779">"ažuriraj obavještenje u stil poziva u toku"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-ca/strings.xml b/testapps/transactionalVoipApp/res/values-ca/strings.xml
index 6780882..06f1655 100644
--- a/testapps/transactionalVoipApp/res/values-ca/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-ca/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Altaveu"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"inicia la reproducció en continu"</string>
+    <string name="crash_app" msgid="2548690390730057704">"llança una excepció"</string>
+    <string name="update_notification" msgid="8677916482672588779">"actualitza la notificació a l\'estil de trucada en curs"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-cs/strings.xml b/testapps/transactionalVoipApp/res/values-cs/strings.xml
index 46a938b..6632765 100644
--- a/testapps/transactionalVoipApp/res/values-cs/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-cs/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Reproduktor"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"zahájit streamování"</string>
+    <string name="crash_app" msgid="2548690390730057704">"vyvolat výjimku"</string>
+    <string name="update_notification" msgid="8677916482672588779">"styl aktualizace oznámení o probíhajícím hovoru"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-da/strings.xml b/testapps/transactionalVoipApp/res/values-da/strings.xml
index e857f3e..1a23b58 100644
--- a/testapps/transactionalVoipApp/res/values-da/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-da/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Højttaler"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"start med at streame"</string>
+    <string name="crash_app" msgid="2548690390730057704">"udløs en undtagelse"</string>
+    <string name="update_notification" msgid="8677916482672588779">"opdateringsnotifikation til igangværende opkaldsstil"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-de/strings.xml b/testapps/transactionalVoipApp/res/values-de/strings.xml
index cf3116c..4f853fc 100644
--- a/testapps/transactionalVoipApp/res/values-de/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-de/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Lautsprecher"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"Streaming starten"</string>
+    <string name="crash_app" msgid="2548690390730057704">"Ausnahme auslösen"</string>
+    <string name="update_notification" msgid="8677916482672588779">"Benachrichtigung zum Stil des laufenden Anrufs aktualisieren"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-el/strings.xml b/testapps/transactionalVoipApp/res/values-el/strings.xml
index d838d2e..5553981 100644
--- a/testapps/transactionalVoipApp/res/values-el/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-el/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Ηχείο"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"έναρξη ροής"</string>
+    <string name="crash_app" msgid="2548690390730057704">"εμφάνιση εξαίρεσης"</string>
+    <string name="update_notification" msgid="8677916482672588779">"ενημέρωση ειδοποίησης στο στιλ κλήσης σε εξέλιξη"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-en-rAU/strings.xml b/testapps/transactionalVoipApp/res/values-en-rAU/strings.xml
index 5bfa1a1..bf68cf5 100644
--- a/testapps/transactionalVoipApp/res/values-en-rAU/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-en-rAU/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"start streaming"</string>
+    <string name="crash_app" msgid="2548690390730057704">"throw exception"</string>
+    <string name="update_notification" msgid="8677916482672588779">"Update notification to ongoing call style"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-en-rCA/strings.xml b/testapps/transactionalVoipApp/res/values-en-rCA/strings.xml
index 1014001..269f0d3 100644
--- a/testapps/transactionalVoipApp/res/values-en-rCA/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-en-rCA/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"start streaming"</string>
+    <string name="crash_app" msgid="2548690390730057704">"throw exception"</string>
+    <string name="update_notification" msgid="8677916482672588779">"update notification to ongoing call style"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-en-rGB/strings.xml b/testapps/transactionalVoipApp/res/values-en-rGB/strings.xml
index 5bfa1a1..bf68cf5 100644
--- a/testapps/transactionalVoipApp/res/values-en-rGB/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-en-rGB/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"start streaming"</string>
+    <string name="crash_app" msgid="2548690390730057704">"throw exception"</string>
+    <string name="update_notification" msgid="8677916482672588779">"Update notification to ongoing call style"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-en-rIN/strings.xml b/testapps/transactionalVoipApp/res/values-en-rIN/strings.xml
index 5bfa1a1..bf68cf5 100644
--- a/testapps/transactionalVoipApp/res/values-en-rIN/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-en-rIN/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"start streaming"</string>
+    <string name="crash_app" msgid="2548690390730057704">"throw exception"</string>
+    <string name="update_notification" msgid="8677916482672588779">"Update notification to ongoing call style"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-en-rXC/strings.xml b/testapps/transactionalVoipApp/res/values-en-rXC/strings.xml
index 40b0016..d94683a 100644
--- a/testapps/transactionalVoipApp/res/values-en-rXC/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-en-rXC/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎‏‎‏‎‏‏‎‏‏‏‎‎‎‎‎‎‎‎‏‎‎‏‎‏‎‏‎‏‎‎‏‏‎‏‏‏‏‎‎‏‎‎‎‎‏‏‎‏‎‎‏‏‏‎‏‎Speaker‎‏‎‎‏‎"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‎‎‏‎‎‏‏‏‎‏‎‎‏‏‏‎‎‎‏‎‎‎‏‎‎‏‏‏‏‏‎‎‏‏‎‎‎‎‏‎‏‎‏‏‏‏‎‎‎Bluetooth‎‏‎‎‏‎"</string>
     <string name="start_stream" msgid="3567634786280097431">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‎‎‎‏‎‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‏‏‏‎start streaming‎‏‎‎‏‎"</string>
+    <string name="crash_app" msgid="2548690390730057704">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‎‏‎‎‎‎‎‏‎‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎‏‎‎‎‎throw exception‎‏‎‎‏‎"</string>
+    <string name="update_notification" msgid="8677916482672588779">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‏‎‎‎‏‎‎‏‏‏‎‎‎‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‏‎update notification to ongoing call style‎‏‎‎‏‎"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-es-rUS/strings.xml b/testapps/transactionalVoipApp/res/values-es-rUS/strings.xml
index 3410a16..da554d1 100644
--- a/testapps/transactionalVoipApp/res/values-es-rUS/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-es-rUS/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Bocina"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"Iniciar transmisión"</string>
+    <string name="crash_app" msgid="2548690390730057704">"generación de excepción"</string>
+    <string name="update_notification" msgid="8677916482672588779">"notificación de actualización del estilo de llamada en curso"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-es/strings.xml b/testapps/transactionalVoipApp/res/values-es/strings.xml
index 2ce1e81..b3f2919 100644
--- a/testapps/transactionalVoipApp/res/values-es/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-es/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Altavoz"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"iniciar emisión"</string>
+    <string name="crash_app" msgid="2548690390730057704">"excepción de expresión \"throw\""</string>
+    <string name="update_notification" msgid="8677916482672588779">"actualizar notificación al estilo de llamada en curso"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-et/strings.xml b/testapps/transactionalVoipApp/res/values-et/strings.xml
index 477dec5..4cc5aab 100644
--- a/testapps/transactionalVoipApp/res/values-et/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-et/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Kõlar"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"käivita voogesitus"</string>
+    <string name="crash_app" msgid="2548690390730057704">"erandi viskamine"</string>
+    <string name="update_notification" msgid="8677916482672588779">"värskendage märguannet käimasoleva kõne stiilis"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-eu/strings.xml b/testapps/transactionalVoipApp/res/values-eu/strings.xml
index 962346f..8b3a181 100644
--- a/testapps/transactionalVoipApp/res/values-eu/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-eu/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Bozgorailua"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetootha"</string>
     <string name="start_stream" msgid="3567634786280097431">"hasi zuzenean igortzen"</string>
+    <string name="crash_app" msgid="2548690390730057704">"eman salbuespena"</string>
+    <string name="update_notification" msgid="8677916482672588779">"eguneratu jakinarazpena, abian den deiaren estiloarekin bat etor dadin"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-fa/strings.xml b/testapps/transactionalVoipApp/res/values-fa/strings.xml
index bd9cddf..88143cb 100644
--- a/testapps/transactionalVoipApp/res/values-fa/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-fa/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"بلندگو"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"بلوتوث"</string>
     <string name="start_stream" msgid="3567634786280097431">"شروع جاری‌سازی"</string>
+    <string name="crash_app" msgid="2548690390730057704">"استثنا قائل شدن"</string>
+    <string name="update_notification" msgid="8677916482672588779">"به‌روزرسانی اعلان به‌سبک تماس درحال انجام"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-fi/strings.xml b/testapps/transactionalVoipApp/res/values-fi/strings.xml
index c95efcb..673d56d 100644
--- a/testapps/transactionalVoipApp/res/values-fi/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-fi/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Kaiutin"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"aloita suoratoisto"</string>
+    <string name="crash_app" msgid="2548690390730057704">"lähetyspoikkeus"</string>
+    <string name="update_notification" msgid="8677916482672588779">"päivitä ilmoitus käynnissä olevan puhelun tyyliin"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-fr-rCA/strings.xml b/testapps/transactionalVoipApp/res/values-fr-rCA/strings.xml
index 64df91c..d58aa13 100644
--- a/testapps/transactionalVoipApp/res/values-fr-rCA/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-fr-rCA/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Haut-parleur"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"démarrer une diffusion"</string>
+    <string name="crash_app" msgid="2548690390730057704">"générer une exception"</string>
+    <string name="update_notification" msgid="8677916482672588779">"modifier la notification en fonction du style de l\'appel en cours"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-fr/strings.xml b/testapps/transactionalVoipApp/res/values-fr/strings.xml
index f1d1bd7..780b8e8 100644
--- a/testapps/transactionalVoipApp/res/values-fr/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-fr/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Haut-parleur"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"démarrer la diffusion"</string>
+    <string name="crash_app" msgid="2548690390730057704">"générer une exception"</string>
+    <string name="update_notification" msgid="8677916482672588779">"modifier la notification en fonction du style de l\'appel en cours"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-gl/strings.xml b/testapps/transactionalVoipApp/res/values-gl/strings.xml
index 76fbb34..f168ab2 100644
--- a/testapps/transactionalVoipApp/res/values-gl/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-gl/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Altofalante"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"iniciar reprodución en tempo real"</string>
+    <string name="crash_app" msgid="2548690390730057704">"activar excepción"</string>
+    <string name="update_notification" msgid="8677916482672588779">"actualiza a notificación en función do estilo da chamada en curso"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-gu/strings.xml b/testapps/transactionalVoipApp/res/values-gu/strings.xml
index b0066da..60bb0b7 100644
--- a/testapps/transactionalVoipApp/res/values-gu/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-gu/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"સ્પીકર"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"બ્લૂટૂથ"</string>
     <string name="start_stream" msgid="3567634786280097431">"સ્ટ્રીમિંગ શરૂ કરો"</string>
+    <string name="crash_app" msgid="2548690390730057704">"અપવાદ થ્રો કરો"</string>
+    <string name="update_notification" msgid="8677916482672588779">"ચાલુ કૉલ શૈલી પર નોટિફિકેશન અપડેટ કરો"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-hi/strings.xml b/testapps/transactionalVoipApp/res/values-hi/strings.xml
index a6e4a10..ba4262a 100644
--- a/testapps/transactionalVoipApp/res/values-hi/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-hi/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"स्पीकर"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ब्लूटूथ"</string>
     <string name="start_stream" msgid="3567634786280097431">"स्ट्रीमिंग शुरू करें"</string>
+    <string name="crash_app" msgid="2548690390730057704">"अपवाद जोड़ें"</string>
+    <string name="update_notification" msgid="8677916482672588779">"मौजूदा कॉल की स्टाइल के हिसाब से सूचनाओं को अपडेट करें"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-hr/strings.xml b/testapps/transactionalVoipApp/res/values-hr/strings.xml
index 768d378..c324f6d 100644
--- a/testapps/transactionalVoipApp/res/values-hr/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-hr/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Zvučnik"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"pokretanje streaminga"</string>
+    <string name="crash_app" msgid="2548690390730057704">"izbacivanje iznimke"</string>
+    <string name="update_notification" msgid="8677916482672588779">"ažuriranje obavijesti u stil poziva u tijeku"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-hu/strings.xml b/testapps/transactionalVoipApp/res/values-hu/strings.xml
index cda3b7e..205404e 100644
--- a/testapps/transactionalVoipApp/res/values-hu/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-hu/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Hangszóró"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"streamelés indítása"</string>
+    <string name="crash_app" msgid="2548690390730057704">"kivétel dobása"</string>
+    <string name="update_notification" msgid="8677916482672588779">"értesítés frissítése a folyamatban lévő hívás stílusára"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-hy/strings.xml b/testapps/transactionalVoipApp/res/values-hy/strings.xml
index b56941f..85e6ae5 100644
--- a/testapps/transactionalVoipApp/res/values-hy/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-hy/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Բարձրախոս"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"սկսել հեռարձակում"</string>
+    <string name="crash_app" msgid="2548690390730057704">"ուղարկել հաղորդագրություն բացառության մասին"</string>
+    <string name="update_notification" msgid="8677916482672588779">"ծանուցում ընթացիկ զանգի ոճի մասին"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-in/strings.xml b/testapps/transactionalVoipApp/res/values-in/strings.xml
index e29fea7..935f036 100644
--- a/testapps/transactionalVoipApp/res/values-in/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-in/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"mulai streaming"</string>
+    <string name="crash_app" msgid="2548690390730057704">"tampilkan pengecualian"</string>
+    <string name="update_notification" msgid="8677916482672588779">"perbarui notifikasi ke gaya panggilan yang sedang berlangsung"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-is/strings.xml b/testapps/transactionalVoipApp/res/values-is/strings.xml
index 4ecb2ca..c0bcd23 100644
--- a/testapps/transactionalVoipApp/res/values-is/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-is/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Hátalari"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"hefja streymi"</string>
+    <string name="crash_app" msgid="2548690390730057704">"nota undantekningu"</string>
+    <string name="update_notification" msgid="8677916482672588779">"uppfæra tilkynningu í stíl símtals sem stendur yfir"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-it/strings.xml b/testapps/transactionalVoipApp/res/values-it/strings.xml
index bb83aa1..36a2816 100644
--- a/testapps/transactionalVoipApp/res/values-it/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-it/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Altoparlante"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"avvia streaming"</string>
+    <string name="crash_app" msgid="2548690390730057704">"genera eccezione"</string>
+    <string name="update_notification" msgid="8677916482672588779">"aggiorna la notifica allo stile di chiamata in corso"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-iw/strings.xml b/testapps/transactionalVoipApp/res/values-iw/strings.xml
index 4de997e..3accc06 100644
--- a/testapps/transactionalVoipApp/res/values-iw/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-iw/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"רמקול"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"התחלת השידור"</string>
+    <string name="crash_app" msgid="2548690390730057704">"חריגה להקפצה של הודעת שגיאה"</string>
+    <string name="update_notification" msgid="8677916482672588779">"עדכון ההתראה לסגנון של שיחה רציפה"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-ja/strings.xml b/testapps/transactionalVoipApp/res/values-ja/strings.xml
index a5e8251..faaede6 100644
--- a/testapps/transactionalVoipApp/res/values-ja/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-ja/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"スピーカー"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"ストリーミングを開始"</string>
+    <string name="crash_app" msgid="2548690390730057704">"例外をスロー"</string>
+    <string name="update_notification" msgid="8677916482672588779">"通話中スタイルへの通知を更新"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-ka/strings.xml b/testapps/transactionalVoipApp/res/values-ka/strings.xml
index 671cffb..6d94f3e 100644
--- a/testapps/transactionalVoipApp/res/values-ka/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-ka/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"დინამიკი"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"სტრიმინგის დაწყება"</string>
+    <string name="crash_app" msgid="2548690390730057704">"ხარვეზის გადასროლა"</string>
+    <string name="update_notification" msgid="8677916482672588779">"განაახლეთ შეტყობინება მიმდინარე ზარის სტილში"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-kk/strings.xml b/testapps/transactionalVoipApp/res/values-kk/strings.xml
index 2713491..03fd031 100644
--- a/testapps/transactionalVoipApp/res/values-kk/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-kk/strings.xml
@@ -28,8 +28,10 @@
     <string name="answer" msgid="5423590397665409939">"жауап беру"</string>
     <string name="set_call_inactive" msgid="7106775211368705195">"setInactive"</string>
     <string name="disconnect_call" msgid="1349412380315371385">"ажырату"</string>
-    <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Динамик"</string>
+    <string name="request_earpiece_endpoint" msgid="6649571985089296573">"Телефон динамигі"</string>
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Динамик"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"трансляцияны бастау"</string>
+    <string name="crash_app" msgid="2548690390730057704">"ерекше жағдай туралы хабарлау"</string>
+    <string name="update_notification" msgid="8677916482672588779">"жүріп жатқан қоңырау стиліндегі хабарландыруды жаңату"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-km/strings.xml b/testapps/transactionalVoipApp/res/values-km/strings.xml
index 13f4983..b3e45e4 100644
--- a/testapps/transactionalVoipApp/res/values-km/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-km/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"ឧបករណ៍​បំពង​សំឡេង"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ប៊្លូធូស"</string>
     <string name="start_stream" msgid="3567634786280097431">"ចាប់ផ្ដើម​ការផ្សាយ"</string>
+    <string name="crash_app" msgid="2548690390730057704">"បោះ​ការលើកលែង"</string>
+    <string name="update_notification" msgid="8677916482672588779">"ធ្វើបច្ចុប្បន្នភាព​ការជូនដំណឹង​ចំពោះ​រចនាប័ទ្ម​នៃការហៅ​ទូរសព្ទ​ដែល​កំពុង​ដំណើរការ"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-kn/strings.xml b/testapps/transactionalVoipApp/res/values-kn/strings.xml
index b994f92..dd3fdd9 100644
--- a/testapps/transactionalVoipApp/res/values-kn/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-kn/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"ಸ್ಪೀಕರ್"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ಬ್ಲೂಟೂತ್"</string>
     <string name="start_stream" msgid="3567634786280097431">"ಸ್ಟ್ರೀಮ್ ಮಾಡುವುದನ್ನು ಪ್ರಾರಂಭಿಸಿ"</string>
+    <string name="crash_app" msgid="2548690390730057704">"ಥ್ರೋ ಎಕ್ಸೆಪ್ಶನ್"</string>
+    <string name="update_notification" msgid="8677916482672588779">"ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಕರೆ ಶೈಲಿಗೆ ನೋಟಿಫಿಕೇಶನ್ ಅನ್ನು ಅಪ್‌ಡೇಟ್ ಮಾಡಿ"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-ko/strings.xml b/testapps/transactionalVoipApp/res/values-ko/strings.xml
index 9eb4556..762dc9c 100644
--- a/testapps/transactionalVoipApp/res/values-ko/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-ko/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"스피커"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"블루투스"</string>
     <string name="start_stream" msgid="3567634786280097431">"스트리밍 시작"</string>
+    <string name="crash_app" msgid="2548690390730057704">"예외 발생"</string>
+    <string name="update_notification" msgid="8677916482672588779">"진행 중인 통화 스타일로 알림 업데이트"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-ky/strings.xml b/testapps/transactionalVoipApp/res/values-ky/strings.xml
index 577dcda..47422a0 100644
--- a/testapps/transactionalVoipApp/res/values-ky/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-ky/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Динамик"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"агымды баштоо"</string>
+    <string name="crash_app" msgid="2548690390730057704">"өзгөчө учурду түзүү"</string>
+    <string name="update_notification" msgid="8677916482672588779">"учурдагы чалуу үчүн жаңыртуу тууралуу билдирменин стили"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-lo/strings.xml b/testapps/transactionalVoipApp/res/values-lo/strings.xml
index 69126d9..1e1d247 100644
--- a/testapps/transactionalVoipApp/res/values-lo/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-lo/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"ລຳໂພງ"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"ເລີ່ມການສະຕຣີມ"</string>
+    <string name="crash_app" msgid="2548690390730057704">"ຂໍ້ຍົກເວັ້ນໃນການໂຍນ"</string>
+    <string name="update_notification" msgid="8677916482672588779">"ອັບເດດການແຈ້ງເຕືອນເປັນຮູບແບບການໂທທີ່ກຳລັງດຳເນີນການຢູ່"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-lt/strings.xml b/testapps/transactionalVoipApp/res/values-lt/strings.xml
index 91e51fe..88cd414 100644
--- a/testapps/transactionalVoipApp/res/values-lt/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-lt/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Garsiakalbis"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"pradėti srautinį perdavimą"</string>
+    <string name="crash_app" msgid="2548690390730057704">"siųsti pranešimą apie išimtį"</string>
+    <string name="update_notification" msgid="8677916482672588779">"atnaujinti pranešimą į vykstančio skambučio stilių"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-lv/strings.xml b/testapps/transactionalVoipApp/res/values-lv/strings.xml
index ae6896f..5e91ffe 100644
--- a/testapps/transactionalVoipApp/res/values-lv/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-lv/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Skaļrunis"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"sākt straumēšanu"</string>
+    <string name="crash_app" msgid="2548690390730057704">"sūtīt ziņojumu par izņēmumu"</string>
+    <string name="update_notification" msgid="8677916482672588779">"atjaunināt paziņojumu atbilstoši pašreizējā zvana stilam"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-mk/strings.xml b/testapps/transactionalVoipApp/res/values-mk/strings.xml
index 8501eaf..d86879d 100644
--- a/testapps/transactionalVoipApp/res/values-mk/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-mk/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Звучник"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"започни стриминг"</string>
+    <string name="crash_app" msgid="2548690390730057704">"отфрли исклучок"</string>
+    <string name="update_notification" msgid="8677916482672588779">"известување за ажурирање на стилот на тековниот повик"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-ml/strings.xml b/testapps/transactionalVoipApp/res/values-ml/strings.xml
index 67e4e34..6c70b22 100644
--- a/testapps/transactionalVoipApp/res/values-ml/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-ml/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"സ്പീക്കർ"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"സ്‌ട്രീമിംഗ് ആരംഭിക്കുക"</string>
+    <string name="crash_app" msgid="2548690390730057704">"ഒഴിവാക്കൽ ത്രോ ചെയ്യുക"</string>
+    <string name="update_notification" msgid="8677916482672588779">"സജീവമായ കോൾ ശൈലിയിലേക്ക് അറിയിപ്പ് അപ്ഡേറ്റ് ചെയ്യുക"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-mn/strings.xml b/testapps/transactionalVoipApp/res/values-mn/strings.xml
index e4b6f36..fecb956 100644
--- a/testapps/transactionalVoipApp/res/values-mn/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-mn/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Чанга яригч"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"дамжуулалтыг эхлүүлэх"</string>
+    <string name="crash_app" msgid="2548690390730057704">"шидэх гажиг"</string>
+    <string name="update_notification" msgid="8677916482672588779">"үргэлжилж буй дуудлагын загварын шинэчлэлтийн мэдэгдэл"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-mr/strings.xml b/testapps/transactionalVoipApp/res/values-mr/strings.xml
index dfb3184..97bf665 100644
--- a/testapps/transactionalVoipApp/res/values-mr/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-mr/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"स्पीकर"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ब्लूटूथ"</string>
     <string name="start_stream" msgid="3567634786280097431">"स्ट्रीम करणे सुरू करा"</string>
+    <string name="crash_app" msgid="2548690390730057704">"एक्सेप्शन जोडा"</string>
+    <string name="update_notification" msgid="8677916482672588779">"सुरू असलेल्या कॉल शैलीवर सूचना अपडेट करा"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-ms/strings.xml b/testapps/transactionalVoipApp/res/values-ms/strings.xml
index 3005391..abcb702 100644
--- a/testapps/transactionalVoipApp/res/values-ms/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-ms/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Pembesar suara"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"mulakan penstriman"</string>
+    <string name="crash_app" msgid="2548690390730057704">"buat pengecualian"</string>
+    <string name="update_notification" msgid="8677916482672588779">"kemas kinikan pemberitahuan kepada gaya panggilan keluar"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-my/strings.xml b/testapps/transactionalVoipApp/res/values-my/strings.xml
index 818a3f7..b8ee395 100644
--- a/testapps/transactionalVoipApp/res/values-my/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-my/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"စပီကာ"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ဘလူးတုသ်"</string>
     <string name="start_stream" msgid="3567634786280097431">"တိုက်ရိုက်လွှင့်ခြင်း စတင်ရန်"</string>
+    <string name="crash_app" msgid="2548690390730057704">"throw exception"</string>
+    <string name="update_notification" msgid="8677916482672588779">"လက်ရှိခေါ်ဆိုမှုပုံစံအတွက် အပ်ဒိတ်အကြောင်းကြားချက်"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-nb/strings.xml b/testapps/transactionalVoipApp/res/values-nb/strings.xml
index ab0353d..22bb06f 100644
--- a/testapps/transactionalVoipApp/res/values-nb/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-nb/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Høyttaler"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"start strømming"</string>
+    <string name="crash_app" msgid="2548690390730057704">"unntak – avbryt med en feil"</string>
+    <string name="update_notification" msgid="8677916482672588779">"oppdater varslingsstil til «Pågående anrop»"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-ne/strings.xml b/testapps/transactionalVoipApp/res/values-ne/strings.xml
index 3a12a70..e9bc805 100644
--- a/testapps/transactionalVoipApp/res/values-ne/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-ne/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"स्पिकर"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ब्लुटुथ"</string>
     <string name="start_stream" msgid="3567634786280097431">"स्ट्रिम गर्न थाल्नुहोस्"</string>
+    <string name="crash_app" msgid="2548690390730057704">"अपवाद देखाउने काम"</string>
+    <string name="update_notification" msgid="8677916482672588779">"कल गरिरहेका बेला सूचना जुन शैलीमा देखिन्छ सोही शैली प्रयोग गर्नुहोस्"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-nl/strings.xml b/testapps/transactionalVoipApp/res/values-nl/strings.xml
index 7c9ce32..1ba3f9c 100644
--- a/testapps/transactionalVoipApp/res/values-nl/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-nl/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"streamen starten"</string>
+    <string name="crash_app" msgid="2548690390730057704">"uitzondering activeren"</string>
+    <string name="update_notification" msgid="8677916482672588779">"updatemelding naar actieve gespreksstijl"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-or/strings.xml b/testapps/transactionalVoipApp/res/values-or/strings.xml
index 7a805f4..f3391ea 100644
--- a/testapps/transactionalVoipApp/res/values-or/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-or/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"ସ୍ପିକର"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ବ୍ଲୁଟୁଥ"</string>
     <string name="start_stream" msgid="3567634786280097431">"ଷ୍ଟ୍ରିମିଂ ଆରମ୍ଭ କରନ୍ତୁ"</string>
+    <string name="crash_app" msgid="2548690390730057704">"ଥ୍ରୋ ଏକ୍ସସେପସନ"</string>
+    <string name="update_notification" msgid="8677916482672588779">"ଚାଲିଥିବା କଲ ଷ୍ଟାଇଲ ପାଇଁ ବିଜ୍ଞପ୍ତିକୁ ଅପଡେଟ କରନ୍ତୁ"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-pa/strings.xml b/testapps/transactionalVoipApp/res/values-pa/strings.xml
index 8293899..76e367d 100644
--- a/testapps/transactionalVoipApp/res/values-pa/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-pa/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"ਸਪੀਕਰ"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"ਬਲੂਟੁੱਥ"</string>
     <string name="start_stream" msgid="3567634786280097431">"ਸਟ੍ਰੀਮਿੰਗ ਸ਼ੁਰੂ ਕਰੋ"</string>
+    <string name="crash_app" msgid="2548690390730057704">"ਅਪਵਾਦ ਸ਼ਾਮਲ ਕਰੋ"</string>
+    <string name="update_notification" msgid="8677916482672588779">"ਜਾਰੀ ਕਾਲ ਸਟਾਈਲ \'ਤੇ ਸੂਚਨਾ ਅੱਪਡੇਟ ਕਰੋ"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-pl/strings.xml b/testapps/transactionalVoipApp/res/values-pl/strings.xml
index 3cb8ac4..c6115b8 100644
--- a/testapps/transactionalVoipApp/res/values-pl/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-pl/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Głośnik"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"rozpocznij transmisję"</string>
+    <string name="crash_app" msgid="2548690390730057704">"wyjątek dotyczący zgłoszenia"</string>
+    <string name="update_notification" msgid="8677916482672588779">"zaktualizuj powiadomienie do stylu trwającej rozmowy"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-pt-rPT/strings.xml b/testapps/transactionalVoipApp/res/values-pt-rPT/strings.xml
index 6c4f149..a5b3ea0 100644
--- a/testapps/transactionalVoipApp/res/values-pt-rPT/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-pt-rPT/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Altifalante"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"Iniciar stream"</string>
+    <string name="crash_app" msgid="2548690390730057704">"acionar exceção"</string>
+    <string name="update_notification" msgid="8677916482672588779">"atualizar estilo de notificação para chamada em curso"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-pt/strings.xml b/testapps/transactionalVoipApp/res/values-pt/strings.xml
index 97bba50..a09c64d 100644
--- a/testapps/transactionalVoipApp/res/values-pt/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-pt/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Alto-falante"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"Iniciar transmissão"</string>
+    <string name="crash_app" msgid="2548690390730057704">"gerar exceção"</string>
+    <string name="update_notification" msgid="8677916482672588779">"notificação de atualização para o estilo \"Chamada em andamento\""</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-ro/strings.xml b/testapps/transactionalVoipApp/res/values-ro/strings.xml
index bb630a8..261a5ad 100644
--- a/testapps/transactionalVoipApp/res/values-ro/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-ro/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Difuzor"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"începe streamingul"</string>
+    <string name="crash_app" msgid="2548690390730057704">"trimite excepție"</string>
+    <string name="update_notification" msgid="8677916482672588779">"actualizează notificarea la stilul de apel în desfășurare"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-ru/strings.xml b/testapps/transactionalVoipApp/res/values-ru/strings.xml
index 87c06f1..c05e7ea 100644
--- a/testapps/transactionalVoipApp/res/values-ru/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-ru/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Колонка"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"Начать трансляцию"</string>
+    <string name="crash_app" msgid="2548690390730057704">"отправить сообщение об исключении"</string>
+    <string name="update_notification" msgid="8677916482672588779">"стиль уведомления об обновлении для текущего звонка"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-si/strings.xml b/testapps/transactionalVoipApp/res/values-si/strings.xml
index c28e166..d8b8a6f 100644
--- a/testapps/transactionalVoipApp/res/values-si/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-si/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"ස්පීකරය"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"බ්ලූටූත්"</string>
     <string name="start_stream" msgid="3567634786280097431">"ප්‍රවාහය අරඹන්න"</string>
+    <string name="crash_app" msgid="2548690390730057704">"ව්‍යතිරේකය දමන්න"</string>
+    <string name="update_notification" msgid="8677916482672588779">"පවතින ඇමතුම් විලාසයට යාවත්කාලීනයේ දැනුම්දීම"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-sk/strings.xml b/testapps/transactionalVoipApp/res/values-sk/strings.xml
index 5e76289..3847882 100644
--- a/testapps/transactionalVoipApp/res/values-sk/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-sk/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Reproduktor"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"spustiť streamovanie"</string>
+    <string name="crash_app" msgid="2548690390730057704">"vyvolať výnimku"</string>
+    <string name="update_notification" msgid="8677916482672588779">"aktualizovať upozornenie na štýl prebiehajúceho hovoru"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-sl/strings.xml b/testapps/transactionalVoipApp/res/values-sl/strings.xml
index 435eac9..dec3622 100644
--- a/testapps/transactionalVoipApp/res/values-sl/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-sl/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Zvočnik"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"začni pretočno predvajanje"</string>
+    <string name="crash_app" msgid="2548690390730057704">"sprožitev izjeme"</string>
+    <string name="update_notification" msgid="8677916482672588779">"posodobi obvestilo na slog trenutnega klica"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-sq/strings.xml b/testapps/transactionalVoipApp/res/values-sq/strings.xml
index 3d18edf..ddaba66 100644
--- a/testapps/transactionalVoipApp/res/values-sq/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-sq/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Altoparlanti"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"nis transmetimin"</string>
+    <string name="crash_app" msgid="2548690390730057704">"gjenero një përjashtim"</string>
+    <string name="update_notification" msgid="8677916482672588779">"përditëso njoftimin me stilin e telefonatës në vazhdim"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-sr/strings.xml b/testapps/transactionalVoipApp/res/values-sr/strings.xml
index df6a08b..cd413f4 100644
--- a/testapps/transactionalVoipApp/res/values-sr/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-sr/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Звучник"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"почните да стримујете"</string>
+    <string name="crash_app" msgid="2548690390730057704">"избацити изузетак"</string>
+    <string name="update_notification" msgid="8677916482672588779">"ажурирајте обавештење на стил актуелног позива"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-sv/strings.xml b/testapps/transactionalVoipApp/res/values-sv/strings.xml
index 51d300a..f74b775 100644
--- a/testapps/transactionalVoipApp/res/values-sv/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-sv/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Högtalare"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"starta streaming"</string>
+    <string name="crash_app" msgid="2548690390730057704">"utlös undantag"</string>
+    <string name="update_notification" msgid="8677916482672588779">"uppdatera avisering till format för pågående samtal"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-sw/strings.xml b/testapps/transactionalVoipApp/res/values-sw/strings.xml
index 3ad2501..b7d0d0f 100644
--- a/testapps/transactionalVoipApp/res/values-sw/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-sw/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Spika"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"anzisha kutiririsha"</string>
+    <string name="crash_app" msgid="2548690390730057704">"hitilafu wakati wa kutekeleza programu"</string>
+    <string name="update_notification" msgid="8677916482672588779">"sasisha arifa kwenye mtindo wa simu inayoendelea"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-ta/strings.xml b/testapps/transactionalVoipApp/res/values-ta/strings.xml
index 884291d..39b410a 100644
--- a/testapps/transactionalVoipApp/res/values-ta/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-ta/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"ஸ்பீக்கர்"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"புளூடூத்"</string>
     <string name="start_stream" msgid="3567634786280097431">"ஸ்ட்ரீமிங்கைத் தொடங்கு"</string>
+    <string name="crash_app" msgid="2548690390730057704">"விதிவிலக்கைத் தொடங்கு"</string>
+    <string name="update_notification" msgid="8677916482672588779">"செயலில் உள்ள அழைப்பு ஸ்டைலுக்கான அறிவிப்பைப் புதுப்பிக்கவும்"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-te/strings.xml b/testapps/transactionalVoipApp/res/values-te/strings.xml
index b926d1a..f4560ab 100644
--- a/testapps/transactionalVoipApp/res/values-te/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-te/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"స్పీకర్"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"బ్లూటూత్"</string>
     <string name="start_stream" msgid="3567634786280097431">"స్ట్రీమింగ్‌ను ప్రారంభించండి"</string>
+    <string name="crash_app" msgid="2548690390730057704">"మినహాయింపు వేయండి"</string>
+    <string name="update_notification" msgid="8677916482672588779">"జరుగుతున్న కాల్ స్టయిల్‌కి నోటిఫికేషన్‌ను అప్‌డేట్ చేయండి"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-th/strings.xml b/testapps/transactionalVoipApp/res/values-th/strings.xml
index a1a9803..545110b 100644
--- a/testapps/transactionalVoipApp/res/values-th/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-th/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"ลำโพง"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"บลูทูธ"</string>
     <string name="start_stream" msgid="3567634786280097431">"เริ่มสตรีมมิง"</string>
+    <string name="crash_app" msgid="2548690390730057704">"ส่งข้อยกเว้น"</string>
+    <string name="update_notification" msgid="8677916482672588779">"อัปเดตการแจ้งเตือนไปยังรูปแบบการโทรที่ดำเนินอยู่"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-tl/strings.xml b/testapps/transactionalVoipApp/res/values-tl/strings.xml
index d3399ff..6cc2a2b 100644
--- a/testapps/transactionalVoipApp/res/values-tl/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-tl/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"simulan ang streaming"</string>
+    <string name="crash_app" msgid="2548690390730057704">"throw exception"</string>
+    <string name="update_notification" msgid="8677916482672588779">"i-update ang notification sa istilo ng kasalukuyang tawag"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-tr/strings.xml b/testapps/transactionalVoipApp/res/values-tr/strings.xml
index d9a94ab..ec23048 100644
--- a/testapps/transactionalVoipApp/res/values-tr/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-tr/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Hoparlör"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"yayın başlat"</string>
+    <string name="crash_app" msgid="2548690390730057704">"istisna gönder"</string>
+    <string name="update_notification" msgid="8677916482672588779">"bildirimi devam eden arama stiline güncelle"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-uk/strings.xml b/testapps/transactionalVoipApp/res/values-uk/strings.xml
index e08728c..0069f3d 100644
--- a/testapps/transactionalVoipApp/res/values-uk/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-uk/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Колонка"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"Почати трансляцію"</string>
+    <string name="crash_app" msgid="2548690390730057704">"надіслати повідомлення про виняток"</string>
+    <string name="update_notification" msgid="8677916482672588779">"стиль сповіщення про оновлення для поточного дзвінка"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-ur/strings.xml b/testapps/transactionalVoipApp/res/values-ur/strings.xml
index e0e0c6e..e41027a 100644
--- a/testapps/transactionalVoipApp/res/values-ur/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-ur/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"اسپیکر"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"بلوٹوتھ"</string>
     <string name="start_stream" msgid="3567634786280097431">"سلسلہ بندی شروع کریں"</string>
+    <string name="crash_app" msgid="2548690390730057704">"تھرو ایکسیپشن"</string>
+    <string name="update_notification" msgid="8677916482672588779">"اطلاع کو جاری کال طرز پر اپ ڈیٹ کریں"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-uz/strings.xml b/testapps/transactionalVoipApp/res/values-uz/strings.xml
index 5421322..faa0b4b 100644
--- a/testapps/transactionalVoipApp/res/values-uz/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-uz/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Karnay"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"strimingni boshlash"</string>
+    <string name="crash_app" msgid="2548690390730057704">"istisno berish"</string>
+    <string name="update_notification" msgid="8677916482672588779">"bildirishnomani joriy chaqiruv uslubida yangilash"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-vi/strings.xml b/testapps/transactionalVoipApp/res/values-vi/strings.xml
index 88362e4..a54d544 100644
--- a/testapps/transactionalVoipApp/res/values-vi/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-vi/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Loa"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"bắt đầu phát trực tuyến"</string>
+    <string name="crash_app" msgid="2548690390730057704">"đưa ra trường hợp ngoại lệ"</string>
+    <string name="update_notification" msgid="8677916482672588779">"cập nhật thông báo thành kiểu cuộc gọi đang diễn ra"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-zh-rCN/strings.xml b/testapps/transactionalVoipApp/res/values-zh-rCN/strings.xml
index 4b816ba..a434e35 100644
--- a/testapps/transactionalVoipApp/res/values-zh-rCN/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-zh-rCN/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"扬声器"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"蓝牙"</string>
     <string name="start_stream" msgid="3567634786280097431">"开始直播"</string>
+    <string name="crash_app" msgid="2548690390730057704">"抛出异常"</string>
+    <string name="update_notification" msgid="8677916482672588779">"将通知更新为当前通话样式"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-zh-rHK/strings.xml b/testapps/transactionalVoipApp/res/values-zh-rHK/strings.xml
index 5b80831..e00caa9 100644
--- a/testapps/transactionalVoipApp/res/values-zh-rHK/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-zh-rHK/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"喇叭"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"藍牙"</string>
     <string name="start_stream" msgid="3567634786280097431">"開始串流播放"</string>
+    <string name="crash_app" msgid="2548690390730057704">"擲回例外狀況"</string>
+    <string name="update_notification" msgid="8677916482672588779">"更新通知至通話中樣式"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-zh-rTW/strings.xml b/testapps/transactionalVoipApp/res/values-zh-rTW/strings.xml
index b8a2045..1a6da94 100644
--- a/testapps/transactionalVoipApp/res/values-zh-rTW/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-zh-rTW/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"喇叭"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"藍牙"</string>
     <string name="start_stream" msgid="3567634786280097431">"開始串流播放"</string>
+    <string name="crash_app" msgid="2548690390730057704">"擲回例外狀況"</string>
+    <string name="update_notification" msgid="8677916482672588779">"將通知更新為通話中樣式"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values-zu/strings.xml b/testapps/transactionalVoipApp/res/values-zu/strings.xml
index 8e14895..cd86e81 100644
--- a/testapps/transactionalVoipApp/res/values-zu/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-zu/strings.xml
@@ -32,4 +32,6 @@
     <string name="request_speaker_endpoint" msgid="1033259535289845405">"Isipikha"</string>
     <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"I-Bluetooth"</string>
     <string name="start_stream" msgid="3567634786280097431">"Qala ukusakaza-bukhoma"</string>
+    <string name="crash_app" msgid="2548690390730057704">"phonsela okuhlukile"</string>
+    <string name="update_notification" msgid="8677916482672588779">"buyekeza isaziso kusitayela sekholi eqhubekayo"</string>
 </resources>
diff --git a/testapps/transactionalVoipApp/res/values/strings.xml b/testapps/transactionalVoipApp/res/values/strings.xml
index 23a5118..8239a0e 100644
--- a/testapps/transactionalVoipApp/res/values/strings.xml
+++ b/testapps/transactionalVoipApp/res/values/strings.xml
@@ -38,5 +38,7 @@
     <string name="request_bluetooth_endpoint">Bluetooth</string>
     <!-- extra functionality -->
     <string name="start_stream">start streaming</string>
+    <string name="crash_app">throw exception</string>
+    <string name="update_notification"> update notification to ongoing call style</string>
 
 </resources>
\ No newline at end of file
diff --git a/testapps/transactionalVoipApp/src/com/android/server/telecom/transactionalVoipApp/InCallActivity.java b/testapps/transactionalVoipApp/src/com/android/server/telecom/transactionalVoipApp/InCallActivity.java
index 3e53800..50556a1 100644
--- a/testapps/transactionalVoipApp/src/com/android/server/telecom/transactionalVoipApp/InCallActivity.java
+++ b/testapps/transactionalVoipApp/src/com/android/server/telecom/transactionalVoipApp/InCallActivity.java
@@ -21,11 +21,9 @@
 import static android.telecom.CallAttributes.DIRECTION_OUTGOING;
 
 import android.app.Activity;
-import android.graphics.Color;
 import android.media.AudioManager;
 import android.media.AudioRecord;
 import android.media.MediaPlayer;
-import android.net.StringNetworkSpecifier;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.OutcomeReceiver;
@@ -164,10 +162,35 @@
                 }
             }
         });
+
+        findViewById(R.id.crash_app).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // To test edge cases, it may be useful to crash the app. To do this, throwing a
+                // RuntimeException is sufficient.
+                throw new RuntimeException(
+                        "Intentionally throwing RuntimeException from InCallActivity");
+            }
+        });
+
+        findViewById(R.id.updateCallStyleNotification).setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        Utils.updateCallStyleNotification_toOngoingCall(getApplicationContext());
+                    }
+                });
+    }
+
+    @Override
+    protected void onStop() {
+        Log.i(TAG, "onStop: InCallActivity has stopped");
+        super.onStop();
     }
 
     @Override
     protected void onDestroy() {
+        Log.i(TAG, "onDestroy: InCallActivity has been destroyed");
         disconnectAndStopAudio();
         super.onDestroy();
     }
@@ -205,7 +228,12 @@
             sb.append("Error Getting Id");
         }
         sb.append("]");
-        view.setText(sb.toString());
+        try {
+            view.setText(sb.toString());
+        }
+        catch (Exception e){
+            // ignore updating the ui
+        }
     }
 
     private void addCall() {
@@ -223,6 +251,7 @@
                     @Override
                     public void onResult(CallControl callControl) {
                         Log.i(TAG, "addCall: onResult: callback fired");
+                        Utils.postIncomingCallStyleNotification(getApplicationContext());
                         mVoipCall.onAddCallControl(callControl);
                         updateCallId();
                         updateCurrentEndpoint();
@@ -247,7 +276,8 @@
         mAudioRecord.stop();
         try {
             mAudioRecord.unregisterAudioRecordingCallback(mAudioRecordingCallback);
-        } catch (IllegalArgumentException e) {
+            Utils.clearNotification(getApplicationContext());
+        } catch (Exception e) {
             // pass through
         }
     }
diff --git a/testapps/transactionalVoipApp/src/com/android/server/telecom/transactionalVoipApp/Utils.java b/testapps/transactionalVoipApp/src/com/android/server/telecom/transactionalVoipApp/Utils.java
index 98de790..ec448b2 100644
--- a/testapps/transactionalVoipApp/src/com/android/server/telecom/transactionalVoipApp/Utils.java
+++ b/testapps/transactionalVoipApp/src/com/android/server/telecom/transactionalVoipApp/Utils.java
@@ -17,6 +17,7 @@
 package com.android.server.telecom.transactionalVoipApp;
 
 import android.app.Notification;
+import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.Person;
 import android.content.ComponentName;
@@ -38,9 +39,11 @@
 
 public class Utils {
     public static final String TAG = "TransactionalAppUtils";
+    public static final String CALLER_NAME = "Sundar Pichai";
     public static final String sEXTRAS_KEY = "ExtrasKey";
     public static final String sCALL_DIRECTION_KEY = "CallDirectionKey";
     public static final String CHANNEL_ID = "TelecomVoipAppChannelId";
+    public static final int CALL_NOTIFICATION_ID = 123456;
     private static final int SAMPLING_RATE_HZ = 44100;
 
     public static final PhoneAccountHandle PHONE_ACCOUNT_HANDLE = new PhoneAccountHandle(
@@ -70,15 +73,52 @@
                 .setContentTitle("Incoming call")
                 .setSmallIcon(R.drawable.ic_android_black_24dp)
                 .setStyle(Notification.CallStyle.forIncomingCall(
-                        new Person.Builder().setName("Tom Stu").setImportant(true).build(),
+                        new Person.Builder().setName(CALLER_NAME).setImportant(true).build(),
                         pendingAnswer, pendingReject)
                 )
                 .setFullScreenIntent(pendingAnswer, true)
+                .setOngoing(true)
                 .build();
 
         return callStyleNotification;
     }
 
+    public static void postIncomingCallStyleNotification(Context context) {
+        NotificationManager nm = context.getSystemService(NotificationManager.class);
+        nm.notify(Utils.CALL_NOTIFICATION_ID, createCallStyleNotification(context));
+    }
+
+    public static void updateCallStyleNotification_toOngoingCall(Context context) {
+        PendingIntent ongoingCall = PendingIntent.getActivity(context, 0,
+                new Intent(""), PendingIntent.FLAG_IMMUTABLE);
+
+        Notification callStyleNotification = new Notification.Builder(context,
+                CHANNEL_ID)
+                .setContentText("active call in the TransactionalTestApp")
+                .setContentTitle("Ongoing call")
+                .setSmallIcon(R.drawable.ic_android_black_24dp)
+                .setStyle(Notification.CallStyle.forOngoingCall(
+                        new Person.Builder().setName(CALLER_NAME).setImportant(true).build(),
+                        ongoingCall)
+                )
+                .setFullScreenIntent(ongoingCall, true)
+                .setOngoing(true)
+                .build();
+
+        NotificationManager notificationManager =
+                context.getSystemService(NotificationManager.class);
+
+        notificationManager.notify(CALL_NOTIFICATION_ID, callStyleNotification);
+    }
+
+    public static void clearNotification(Context context) {
+        NotificationManager notificationManager =
+                context.getSystemService(NotificationManager.class);
+        if (notificationManager != null) {
+            notificationManager.cancel(CALL_NOTIFICATION_ID);
+        }
+    }
+
     public static MediaPlayer createMediaPlayer(Context context) {
         int audioToPlay = (Math.random() > 0.5f) ?
                 com.android.server.telecom.transactionalVoipApp.R.raw.sample_audio :
diff --git a/testapps/transactionalVoipApp/src/com/android/server/telecom/transactionalVoipApp/VoipAppMainActivity.java b/testapps/transactionalVoipApp/src/com/android/server/telecom/transactionalVoipApp/VoipAppMainActivity.java
index ae7d9d0..72a3906 100644
--- a/testapps/transactionalVoipApp/src/com/android/server/telecom/transactionalVoipApp/VoipAppMainActivity.java
+++ b/testapps/transactionalVoipApp/src/com/android/server/telecom/transactionalVoipApp/VoipAppMainActivity.java
@@ -99,8 +99,6 @@
     }
 
     private void startInCallActivity(int direction) {
-        mNotificationManager.notify(123456,
-                Utils.createCallStyleNotification(getApplicationContext()));
         Bundle extras = new Bundle();
         extras.putInt(Utils.sCALL_DIRECTION_KEY, direction);
         Intent intent = new Intent(getApplicationContext(), InCallActivity.class);
@@ -142,6 +140,7 @@
     protected void onDestroy() {
         Log.i(TAG, ACT_STATE_TAG + " onDestroy: is called before the activity is"
                 + " destroyed. ");
+        Utils.clearNotification(getApplicationContext());
         super.onDestroy();
     }
 }
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index 9047da3..bd81a2f 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -16,8 +16,11 @@
 
 package com.android.server.telecom.tests;
 
+import static com.android.server.telecom.tests.ConnectionServiceFixture.STATUS_HINTS_EXTRA;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.nullable;
@@ -38,10 +41,14 @@
 import android.content.IContentProvider;
 import android.content.pm.PackageManager;
 import android.media.AudioDeviceInfo;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
 import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -55,12 +62,14 @@
 import android.telecom.ParcelableCall;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
+import android.telecom.StatusHints;
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
 
 import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
 
 import com.android.internal.telecom.IInCallAdapter;
 import android.telecom.CallerInfo;
@@ -196,7 +205,7 @@
     @Test
     public void testTelecomManagerAcceptRingingVideoCall() throws Exception {
         IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
-                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
 
         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
@@ -225,7 +234,7 @@
     @Test
     public void testTelecomManagerAcceptRingingVideoCallAsAudio() throws Exception {
         IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
-                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
 
         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
@@ -256,7 +265,7 @@
     @Test
     public void testTelecomManagerAcceptRingingInvalidVideoState() throws Exception {
         IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
-                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
 
         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
@@ -694,13 +703,13 @@
     @MediumTest
     @Test
     public void testBasicConferenceCall() throws Exception {
-        makeConferenceCall();
+        makeConferenceCall(null, null);
     }
 
     @MediumTest
     @Test
     public void testAddCallToConference1() throws Exception {
-        ParcelableCall conferenceCall = makeConferenceCall();
+        ParcelableCall conferenceCall = makeConferenceCall(null, null);
         IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
         // testAddCallToConference{1,2} differ in the order of arguments to InCallAdapter#conference
@@ -718,7 +727,7 @@
     @MediumTest
     @Test
     public void testAddCallToConference2() throws Exception {
-        ParcelableCall conferenceCall = makeConferenceCall();
+        ParcelableCall conferenceCall = makeConferenceCall(null, null);
         IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
         mInCallServiceFixtureX.getInCallAdapter()
@@ -976,7 +985,7 @@
     public void testOutgoingCallSelectPhoneAccountVideo() throws Exception {
         startOutgoingPhoneCallPendingCreateConnection("650-555-1212",
                 null, mConnectionServiceFixtureA,
-                Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL);
+                Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL, null);
         com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
                 .iterator().next();
         assert(call.isVideoCallingSupportedByPhoneAccount());
@@ -999,7 +1008,7 @@
     public void testOutgoingCallSelectPhoneAccountNoVideo() throws Exception {
         startOutgoingPhoneCallPendingCreateConnection("650-555-1212",
                 null, mConnectionServiceFixtureA,
-                Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL);
+                Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL, null);
         com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
                 .iterator().next();
         assert(call.isVideoCallingSupportedByPhoneAccount());
@@ -1214,4 +1223,145 @@
         assertTrue(muteValues.get(0));
         assertFalse(muteValues.get(1));
     }
+
+    /**
+     * Verifies that StatusHints image is validated in ConnectionServiceWrapper#addConferenceCall
+     * when the image doesn't belong to the calling user. Simulates a scenario where an app
+     * could manipulate the contents of the bundle and send it via the binder to upload an image
+     * from another user.
+     *
+     * @throws Exception
+     */
+    @SmallTest
+    @Test
+    public void testValidateStatusHintsImage_addConferenceCall() throws Exception {
+        Intent callIntent1 = new Intent();
+        // Stub intent for call2
+        Intent callIntent2 = new Intent();
+        Bundle callExtras1 = new Bundle();
+        Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
+        // Load StatusHints extra into TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS to be processed
+        // as the call extras. This will be leveraged in ConnectionServiceFixture to set the
+        // StatusHints for the given connection.
+        StatusHints statusHints = new StatusHints(icon);
+        assertNotNull(statusHints.getIcon());
+        callExtras1.putParcelable(STATUS_HINTS_EXTRA, statusHints);
+        callIntent1.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, callExtras1);
+
+        // Start conference call to invoke ConnectionServiceWrapper#addConferenceCall.
+        // Note that the calling user would be User 0.
+        ParcelableCall conferenceCall = makeConferenceCall(callIntent1, callIntent2);
+
+        // Ensure that StatusHints was set.
+        assertNotNull(mInCallServiceFixtureX.getCall(mInCallServiceFixtureX.mLatestCallId)
+                .getStatusHints());
+        // Ensure that the StatusHints image icon was disregarded.
+        assertNull(mInCallServiceFixtureX.getCall(mInCallServiceFixtureX.mLatestCallId)
+                .getStatusHints().getIcon());
+    }
+
+    /**
+     * Verifies that StatusHints image is validated in
+     * ConnectionServiceWrapper#handleCreateConnectionComplete when the image doesn't belong to the
+     * calling user. Simulates a scenario where an app could manipulate the contents of the
+     * bundle and send it via the binder to upload an image from another user.
+     *
+     * @throws Exception
+     */
+    @SmallTest
+    @Test
+    public void testValidateStatusHintsImage_handleCreateConnectionComplete() throws Exception {
+        Bundle extras = new Bundle();
+        Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
+        // Load the bundle with the test extra in order to simulate an app directly invoking the
+        // binder on ConnectionServiceWrapper#handleCreateConnectionComplete.
+        StatusHints statusHints = new StatusHints(icon);
+        assertNotNull(statusHints.getIcon());
+        extras.putParcelable(STATUS_HINTS_EXTRA, statusHints);
+
+        // Start incoming call with StatusHints extras
+        // Note that the calling user in ConnectionServiceWrapper#handleCreateConnectionComplete
+        // would be User 0.
+        IdPair ids = startIncomingPhoneCallWithExtras("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, extras);
+
+        // Ensure that StatusHints was set.
+        assertNotNull(mInCallServiceFixtureX.getCall(ids.mCallId).getStatusHints());
+        // Ensure that the StatusHints image icon was disregarded.
+        assertNull(mInCallServiceFixtureX.getCall(ids.mCallId).getStatusHints().getIcon());
+    }
+
+    /**
+     * Verifies that StatusHints image is validated in ConnectionServiceWrapper#setStatusHints
+     * when the image doesn't belong to the calling user. Simulates a scenario where an app
+     * could manipulate the contents of the bundle and send it via the binder to upload an image
+     * from another user.
+     *
+     * @throws Exception
+     */
+    @SmallTest
+    @Test
+    public void testValidateStatusHintsImage_setStatusHints() throws Exception {
+        IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1214",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+        // Modify existing connection with StatusHints image exploit
+        Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
+        StatusHints statusHints = new StatusHints(icon);
+        assertNotNull(statusHints.getIcon());
+        ConnectionServiceFixture.ConnectionInfo connectionInfo = mConnectionServiceFixtureA
+                .mConnectionById.get(outgoing.mConnectionId);
+        connectionInfo.statusHints = statusHints;
+
+        // Invoke ConnectionServiceWrapper#setStatusHints.
+        // Note that the calling user would be User 0.
+        mConnectionServiceFixtureA.sendSetStatusHints(outgoing.mConnectionId);
+        waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
+                TEST_TIMEOUT);
+
+        // Ensure that StatusHints was set.
+        assertNotNull(mInCallServiceFixtureX.getCall(outgoing.mCallId).getStatusHints());
+        // Ensure that the StatusHints image icon was disregarded.
+        assertNull(mInCallServiceFixtureX.getCall(outgoing.mCallId)
+                .getStatusHints().getIcon());
+    }
+
+    /**
+     * Verifies that StatusHints image is validated in
+     * ConnectionServiceWrapper#addExistingConnection when the image doesn't belong to the calling
+     * user. Simulates a scenario where an app could manipulate the contents of the bundle and
+     * send it via the binder to upload an image from another user.
+     *
+     * @throws Exception
+     */
+    @SmallTest
+    @Test
+    public void testValidateStatusHintsImage_addExistingConnection() throws Exception {
+        IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1214",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+        Connection existingConnection = mConnectionServiceFixtureA.mLatestConnection;
+
+        // Modify existing connection with StatusHints image exploit
+        Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
+        StatusHints modifiedStatusHints = new StatusHints(icon);
+        assertNotNull(modifiedStatusHints.getIcon());
+        ConnectionServiceFixture.ConnectionInfo connectionInfo = mConnectionServiceFixtureA
+                .mConnectionById.get(outgoing.mConnectionId);
+        connectionInfo.statusHints = modifiedStatusHints;
+
+        // Invoke ConnectionServiceWrapper#addExistingConnection.
+        // Note that the calling user would be User 0.
+        mConnectionServiceFixtureA.sendAddExistingConnection(outgoing.mConnectionId);
+        waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
+                TEST_TIMEOUT);
+
+        // Ensure that StatusHints was set. Due to test setup, the ParcelableConnection object that
+        // is passed into sendAddExistingConnection is instantiated on invocation. The call's
+        // StatusHints are not updated at the time of completion, so instead, we can verify that
+        // the ParcelableConnection object was modified.
+        assertNotNull(mConnectionServiceFixtureA.mLatestParcelableConnection.getStatusHints());
+        // Ensure that the StatusHints image icon was disregarded.
+        assertNull(mConnectionServiceFixtureA.mLatestParcelableConnection
+                .getStatusHints().getIcon());
+    }
 }
diff --git a/tests/src/com/android/server/telecom/tests/CallExtrasTest.java b/tests/src/com/android/server/telecom/tests/CallExtrasTest.java
index 926d740..cf44cfe 100644
--- a/tests/src/com/android/server/telecom/tests/CallExtrasTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallExtrasTest.java
@@ -370,7 +370,7 @@
     @LargeTest
     @Test
     public void testConferenceSetExtras() throws Exception {
-        ParcelableCall call = makeConferenceCall();
+        ParcelableCall call = makeConferenceCall(null, null);
         String conferenceId = call.getId();
 
         Conference conference = mConnectionServiceFixtureA.mLatestConference;
@@ -414,7 +414,7 @@
     @FlakyTest(bugId = 117751305)
     @Test
     public void testConferenceExtraOperations() throws Exception {
-        ParcelableCall call = makeConferenceCall();
+        ParcelableCall call = makeConferenceCall(null, null);
         String conferenceId = call.getId();
         Conference conference = mConnectionServiceFixtureA.mLatestConference;
         assertNotNull(conference);
@@ -450,7 +450,7 @@
     @LargeTest
     @Test
     public void testConferenceICS() throws Exception {
-        ParcelableCall call = makeConferenceCall();
+        ParcelableCall call = makeConferenceCall(null, null);
         String conferenceId = call.getId();
         Conference conference = mConnectionServiceFixtureA.mLatestConference;
 
diff --git a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
index b9f5667..9466220 100644
--- a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
@@ -1062,7 +1062,7 @@
         when(fakeCall.getVideoStateHistory()).thenReturn(callVideoState);
         when(fakeCall.getPostDialDigits()).thenReturn(postDialDigits);
         when(fakeCall.getViaNumber()).thenReturn(viaNumber);
-        when(fakeCall.getInitiatingUser()).thenReturn(initiatingUser);
+        when(fakeCall.getAssociatedUser()).thenReturn(initiatingUser);
         when(fakeCall.getCallDataUsage()).thenReturn(callDataUsage);
         when(fakeCall.isEmergencyCall()).thenReturn(
                 phoneAccountHandle.equals(EMERGENCY_ACCT_HANDLE));
diff --git a/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java b/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java
index d95a0e2..4d8d497 100644
--- a/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java
@@ -129,7 +129,7 @@
 
         when(mCallsManager.getCurrentUserHandle()).thenReturn(UserHandle.CURRENT);
         when(mCall.getId()).thenReturn(CALL_ID);
-        when(mCall.getUserHandleFromTargetPhoneAccount()).
+        when(mCall.getAssociatedUser()).
                 thenReturn(PA_HANDLE.getUserHandle());
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mContext.getSystemService(TelecomManager.class))
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index 8a7d22c..9f46336 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -62,7 +62,6 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.BlockedNumberContract;
-import android.provider.Telephony;
 import android.telecom.CallException;
 import android.telecom.CallScreeningService;
 import android.telecom.CallerInfo;
@@ -156,6 +155,8 @@
     private static final int TEST_TIMEOUT = 5000;  // milliseconds
     private static final long STATE_TIMEOUT = 5000L;
     private static final int SECONDARY_USER_ID = 12;
+    private static final UserHandle TEST_USER_HANDLE = UserHandle.of(123);
+    private static final String TEST_PACKAGE_NAME = "GoogleMeet";
     private static final PhoneAccountHandle SIM_1_HANDLE = new PhoneAccountHandle(
             ComponentName.unflattenFromString("com.foo/.Blah"), "Sim1");
     private static final PhoneAccountHandle SIM_1_HANDLE_SECONDARY = new PhoneAccountHandle(
@@ -173,6 +174,10 @@
             ComponentName.unflattenFromString("com.baz/.Self"), "Self");
     private static final PhoneAccountHandle SELF_MANAGED_2_HANDLE = new PhoneAccountHandle(
             ComponentName.unflattenFromString("com.baz/.Self2"), "Self2");
+    private static final PhoneAccountHandle WORK_HANDLE = new PhoneAccountHandle(
+            ComponentName.unflattenFromString("com.foo/.Blah"), "work", new UserHandle(10));
+    private static final PhoneAccountHandle SELF_MANAGED_W_CUSTOM_HANDLE = new PhoneAccountHandle(
+            new ComponentName(TEST_PACKAGE_NAME, "class"), "1", TEST_USER_HANDLE);
     private static final PhoneAccount SIM_1_ACCOUNT = new PhoneAccount.Builder(SIM_1_HANDLE, "Sim1")
             .setCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION
                     | PhoneAccount.CAPABILITY_CALL_PROVIDER
@@ -202,6 +207,19 @@
             .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
             .setIsEnabled(true)
             .build();
+    private static final PhoneAccount WORK_ACCOUNT = new PhoneAccount.Builder(
+            WORK_HANDLE, "work")
+            .setCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION
+                    | PhoneAccount.CAPABILITY_CALL_PROVIDER
+                    | PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)
+            .setIsEnabled(true)
+            .build();
+    private static final PhoneAccount SM_W_DIFFERENT_PACKAGE_AND_USER = new PhoneAccount.Builder(
+            SELF_MANAGED_W_CUSTOM_HANDLE, "Self")
+            .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
+            .setIsEnabled(true)
+            .build();
+
     private static final Uri TEST_ADDRESS = Uri.parse("tel:555-1212");
     private static final Uri TEST_ADDRESS2 = Uri.parse("tel:555-1213");
     private static final Uri TEST_ADDRESS3 = Uri.parse("tel:555-1214");
@@ -338,6 +356,8 @@
                 eq(SIM_1_HANDLE), any())).thenReturn(SIM_1_ACCOUNT);
         when(mPhoneAccountRegistrar.getPhoneAccount(
                 eq(SIM_2_HANDLE), any())).thenReturn(SIM_2_ACCOUNT);
+        when(mPhoneAccountRegistrar.getPhoneAccount(
+                eq(WORK_HANDLE), any())).thenReturn(WORK_ACCOUNT);
         when(mToastFactory.makeText(any(), anyInt(), anyInt())).thenReturn(mToast);
         when(mToastFactory.makeText(any(), any(), anyInt())).thenReturn(mToast);
     }
@@ -2473,7 +2493,7 @@
     public void testPostCallPackageNameSetOnSuccessfulOutgoingCall() throws Exception {
         Call outgoingCall = addSpyCall(CallState.NEW);
         when(mCallsManager.getRoleManagerAdapter().getDefaultCallScreeningApp(
-                outgoingCall.getUserHandleFromTargetPhoneAccount()))
+                outgoingCall.getAssociatedUser()))
                 .thenReturn(DEFAULT_CALL_SCREENING_APP);
         assertNull(outgoingCall.getPostCallPackageName());
         mCallsManager.onSuccessfulOutgoingCall(outgoingCall, CallState.CONNECTING);
@@ -2482,7 +2502,30 @@
 
     @SmallTest
     @Test
-    public void testRejectIncomingCallOnPAHInactive() throws Exception {
+    public void testRejectIncomingCallOnPAHInactive_SecondaryUser() throws Exception {
+        ConnectionServiceWrapper service = mock(ConnectionServiceWrapper.class);
+        doReturn(WORK_HANDLE.getComponentName()).when(service).getComponentName();
+        mCallsManager.addConnectionServiceRepositoryCache(WORK_HANDLE.getComponentName(),
+                WORK_HANDLE.getUserHandle(), service);
+
+        UserManager um = mContext.getSystemService(UserManager.class);
+        UserHandle newUser = new UserHandle(11);
+        when(mCallsManager.getCurrentUserHandle()).thenReturn(newUser);
+        when(um.isUserAdmin(eq(newUser.getIdentifier()))).thenReturn(false);
+        when(um.isQuietModeEnabled(eq(WORK_HANDLE.getUserHandle()))).thenReturn(false);
+        when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(eq(WORK_HANDLE)))
+                .thenReturn(WORK_ACCOUNT);
+        Call newCall = mCallsManager.processIncomingCallIntent(
+                WORK_HANDLE, new Bundle(), false);
+
+        verify(service, timeout(TEST_TIMEOUT)).createConnectionFailed(any());
+        assertFalse(newCall.isInECBM());
+        assertEquals(USER_MISSED_NOT_RUNNING, newCall.getMissedReason());
+    }
+
+    @SmallTest
+    @Test
+    public void testRejectIncomingCallOnPAHInactive_ProfilePaused() throws Exception {
         ConnectionServiceWrapper service = mock(ConnectionServiceWrapper.class);
         doReturn(SIM_2_HANDLE.getComponentName()).when(service).getComponentName();
         mCallsManager.addConnectionServiceRepositoryCache(SIM_2_HANDLE.getComponentName(),
@@ -2519,6 +2562,30 @@
 
     @SmallTest
     @Test
+    public void testAcceptIncomingCallOnPAHInactiveAndECBMActive_SecondaryUser() throws Exception {
+        ConnectionServiceWrapper service = mock(ConnectionServiceWrapper.class);
+        doReturn(WORK_HANDLE.getComponentName()).when(service).getComponentName();
+        mCallsManager.addConnectionServiceRepositoryCache(SIM_2_HANDLE.getComponentName(),
+                WORK_HANDLE.getUserHandle(), service);
+
+        when(mEmergencyCallHelper.isLastOutgoingEmergencyCallPAH(eq(WORK_HANDLE)))
+                .thenReturn(true);
+        UserManager um = mContext.getSystemService(UserManager.class);
+        UserHandle newUser = new UserHandle(11);
+        when(mCallsManager.getCurrentUserHandle()).thenReturn(newUser);
+        when(um.isUserAdmin(eq(newUser.getIdentifier()))).thenReturn(false);
+        when(um.isQuietModeEnabled(eq(WORK_HANDLE.getUserHandle()))).thenReturn(false);
+        when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(eq(WORK_HANDLE)))
+                .thenReturn(WORK_ACCOUNT);
+        Call newCall = mCallsManager.processIncomingCallIntent(
+                WORK_HANDLE, new Bundle(), false);
+
+        assertTrue(newCall.isInECBM());
+        verify(service, timeout(TEST_TIMEOUT).times(0)).createConnectionFailed(any());
+    }
+
+    @SmallTest
+    @Test
     public void testAcceptIncomingEmergencyCallOnPAHInactive() throws Exception {
         ConnectionServiceWrapper service = mock(ConnectionServiceWrapper.class);
         doReturn(SIM_2_HANDLE.getComponentName()).when(service).getComponentName();
@@ -3078,6 +3145,112 @@
                 eq(false));
     }
 
+    /**
+     * Verify CallsManager#isInSelfManagedCall(packageName, userHandle) returns true when
+     * CallsManager is first made aware of the incoming call in processIncomingCallIntent.
+     */
+    @SmallTest
+    @Test
+    public void testAddNewIncomingCall_IsInSelfManagedCall() {
+        // GIVEN
+        assertEquals(0, mCallsManager.getSelfManagedCallsBeingSetup().size());
+        assertFalse(mCallsManager.isInSelfManagedCall(TEST_PACKAGE_NAME, TEST_USER_HANDLE));
+
+        // WHEN
+        when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(any()))
+                .thenReturn(SM_W_DIFFERENT_PACKAGE_AND_USER);
+        UserManager um = mContext.getSystemService(UserManager.class);
+        when(um.isUserAdmin(eq(mCallsManager.getCurrentUserHandle().getIdentifier())))
+                .thenReturn(true);
+
+        // THEN
+        mCallsManager.processIncomingCallIntent(SELF_MANAGED_W_CUSTOM_HANDLE, new Bundle(), false);
+
+        assertEquals(1, mCallsManager.getSelfManagedCallsBeingSetup().size());
+        assertTrue(mCallsManager.isInSelfManagedCall(TEST_PACKAGE_NAME, TEST_USER_HANDLE));
+        assertEquals(0, mCallsManager.getCalls().size());
+    }
+
+    /**
+     * Verify CallsManager#isInSelfManagedCall(packageName, userHandle) returns true when
+     * CallsManager is first made aware of the outgoing call in StartOutgoingCall.
+     */
+    @SmallTest
+    @Test
+    public void testStartOutgoing_IsInSelfManagedCall() {
+        // GIVEN
+        assertEquals(0, mCallsManager.getSelfManagedCallsBeingSetup().size());
+        assertFalse(mCallsManager.isInSelfManagedCall(TEST_PACKAGE_NAME, TEST_USER_HANDLE));
+
+        // WHEN
+        when(mPhoneAccountRegistrar.getPhoneAccount(any(), any()))
+                .thenReturn(SM_W_DIFFERENT_PACKAGE_AND_USER);
+        // Ensure contact info lookup succeeds
+        doAnswer(invocation -> {
+            Uri handle = invocation.getArgument(0);
+            CallerInfo info = new CallerInfo();
+            CompletableFuture<Pair<Uri, CallerInfo>> callerInfoFuture = new CompletableFuture<>();
+            callerInfoFuture.complete(new Pair<>(handle, info));
+            return callerInfoFuture;
+        }).when(mCallerInfoLookupHelper).startLookup(any(Uri.class));
+        // Ensure we have candidate phone account handle info.
+        when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
+                SELF_MANAGED_W_CUSTOM_HANDLE);
+        when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
+                any(), anyInt(), anyInt(), anyBoolean())).thenReturn(
+                new ArrayList<>(List.of(SELF_MANAGED_W_CUSTOM_HANDLE)));
+
+        // THEN
+        mCallsManager.startOutgoingCall(TEST_ADDRESS, SELF_MANAGED_W_CUSTOM_HANDLE, new Bundle(),
+                TEST_USER_HANDLE, new Intent(), TEST_PACKAGE_NAME);
+
+        assertEquals(1, mCallsManager.getSelfManagedCallsBeingSetup().size());
+        assertTrue(mCallsManager.isInSelfManagedCall(TEST_PACKAGE_NAME, TEST_USER_HANDLE));
+        assertEquals(0, mCallsManager.getCalls().size());
+    }
+
+    /**
+     * Verify SelfManagedCallsBeingSetup is being cleaned up in CallsManager#addCall and
+     * CallsManager#removeCall.  This ensures no memory leaks.
+     */
+    @SmallTest
+    @Test
+    public void testCallsBeingSetupCleanup() {
+        Call spyCall = addSpyCall();
+        assertEquals(0, mCallsManager.getSelfManagedCallsBeingSetup().size());
+        // verify CallsManager#removeCall removes the call from SelfManagedCallsBeingSetup
+        mCallsManager.addCallBeingSetup(spyCall);
+        mCallsManager.removeCall(spyCall);
+        assertEquals(0, mCallsManager.getSelfManagedCallsBeingSetup().size());
+        // verify CallsManager#addCall removes the call from SelfManagedCallsBeingSetup
+        mCallsManager.addCallBeingSetup(spyCall);
+        mCallsManager.addCall(spyCall);
+        assertEquals(0, mCallsManager.getSelfManagedCallsBeingSetup().size());
+    }
+
+    /**
+     * Verify isInSelfManagedCall returns false if there is a self-managed call, but it is for a
+     * different package and user
+     */
+    @SmallTest
+    @Test
+    public void testIsInSelfManagedCall_PackageUserQueryIsWorkingAsIntended() {
+        // start an active call
+        Call randomCall = createSpyCall(SELF_MANAGED_HANDLE, CallState.ACTIVE);
+        mCallsManager.addCallBeingSetup(randomCall);
+        assertEquals(1, mCallsManager.getSelfManagedCallsBeingSetup().size());
+        // query isInSelfManagedCall for a package that is NOT in a call;  expect false
+        assertFalse(mCallsManager.isInSelfManagedCall(TEST_PACKAGE_NAME, TEST_USER_HANDLE));
+        // start another call
+        Call targetCall = addSpyCall(SELF_MANAGED_W_CUSTOM_HANDLE, CallState.DIALING);
+        when(targetCall.getTargetPhoneAccount()).thenReturn(SELF_MANAGED_W_CUSTOM_HANDLE);
+        when(targetCall.isSelfManaged()).thenReturn(true);
+        mCallsManager.addCallBeingSetup(targetCall);
+        // query isInSelfManagedCall for a package that is in a call
+        assertTrue(mCallsManager.isInSelfManagedCall(TEST_PACKAGE_NAME, TEST_USER_HANDLE));
+    }
+
+
     private Call addSpyCall() {
         return addSpyCall(SIM_2_HANDLE, CallState.ACTIVE);
     }
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
index c8da78c..0927b80 100755
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
@@ -69,6 +69,9 @@
     static int INVALID_VIDEO_STATE = -1;
     public CountDownLatch mExtrasLock = new CountDownLatch(1);
     static int NOT_SPECIFIED = 0;
+    public static final String STATUS_HINTS_EXTRA = "updateStatusHints";
+    public static final PhoneAccountHandle TEST_PHONE_ACCOUNT_HANDLE =
+            new PhoneAccountHandle(new ComponentName("pkg", "cls"), "test");
 
     /**
      * Implementation of ConnectionService that performs no-ops for tasks normally meant for
@@ -103,6 +106,11 @@
             if (mProperties != NOT_SPECIFIED) {
                 fakeConnection.setConnectionProperties(mProperties);
             }
+            // Testing for StatusHints image icon cross user access
+            if (request.getExtras() != null) {
+                fakeConnection.setStatusHints(
+                        request.getExtras().getParcelable(STATUS_HINTS_EXTRA));
+            }
 
             return fakeConnection;
         }
@@ -119,6 +127,11 @@
             if (mProperties != NOT_SPECIFIED) {
                 fakeConnection.setConnectionProperties(mProperties);
             }
+            // Testing for StatusHints image icon cross user access
+            if (request.getExtras() != null) {
+                fakeConnection.setStatusHints(
+                        request.getExtras().getParcelable(STATUS_HINTS_EXTRA));
+            }
             return fakeConnection;
         }
 
@@ -135,6 +148,12 @@
                 Conference fakeConference = new FakeConference();
                 fakeConference.addConnection(cxn1);
                 fakeConference.addConnection(cxn2);
+                if (cxn1.getStatusHints() != null || cxn2.getStatusHints() != null) {
+                    // For testing purposes, pick one of the status hints that isn't null.
+                    StatusHints statusHints = cxn1.getStatusHints() != null
+                            ? cxn1.getStatusHints() : cxn2.getStatusHints();
+                    fakeConference.setStatusHints(statusHints);
+                }
                 mLatestConference = fakeConference;
                 addConference(fakeConference);
             } else {
@@ -179,7 +198,7 @@
 
     public class FakeConference extends Conference {
         public FakeConference() {
-            super(null);
+            super(TEST_PHONE_ACCOUNT_HANDLE);
             setConnectionCapabilities(
                     Connection.CAPABILITY_SUPPORT_HOLD
                             | Connection.CAPABILITY_HOLD
@@ -507,6 +526,7 @@
 
     public String mLatestConnectionId;
     public Connection mLatestConnection;
+    public ParcelableConnection mLatestParcelableConnection;
     public Conference mLatestConference;
     public final Set<IConnectionServiceAdapter> mConnectionServiceAdapters = new HashSet<>();
     public final Map<String, ConnectionInfo> mConnectionById = new HashMap<>();
@@ -751,7 +771,7 @@
     }
 
     private ParcelableConnection parcelable(ConnectionInfo c) {
-        return new ParcelableConnection(
+        mLatestParcelableConnection = new ParcelableConnection(
                 c.request.getAccountHandle(),
                 c.state,
                 c.capabilities,
@@ -772,5 +792,6 @@
                 c.conferenceableConnectionIds,
                 c.extras,
                 c.callerNumberVerificationStatus);
+        return mLatestParcelableConnection;
     }
 }
diff --git a/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java b/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java
index dbcab66..8a85a87 100644
--- a/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java
+++ b/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java
@@ -144,7 +144,7 @@
                 });
         when(mMockAccountRegistrar.getAllPhoneAccounts(any(UserHandle.class), anyBoolean()))
                 .thenReturn(phoneAccounts);
-        when(mMockCall.getUserHandleFromTargetPhoneAccount()).
+        when(mMockCall.getAssociatedUser()).
                 thenReturn(Binder.getCallingUserHandle());
     }
 
diff --git a/tests/src/com/android/server/telecom/tests/DisconnectedCallNotifierTest.java b/tests/src/com/android/server/telecom/tests/DisconnectedCallNotifierTest.java
index 2cdc23a..05c5071 100644
--- a/tests/src/com/android/server/telecom/tests/DisconnectedCallNotifierTest.java
+++ b/tests/src/com/android/server/telecom/tests/DisconnectedCallNotifierTest.java
@@ -151,6 +151,7 @@
         when(call.getDisconnectCause()).thenReturn(cause);
         when(call.getTargetPhoneAccount()).thenReturn(PHONE_ACCOUNT_HANDLE);
         when(call.getHandle()).thenReturn(TEL_CALL_HANDLE);
+        when(call.getAssociatedUser()).thenReturn(PHONE_ACCOUNT_HANDLE.getUserHandle());
         return call;
     }
 }
diff --git a/tests/src/com/android/server/telecom/tests/HeadsetMediaButtonTest.java b/tests/src/com/android/server/telecom/tests/HeadsetMediaButtonTest.java
index ce23724..0bfa987 100644
--- a/tests/src/com/android/server/telecom/tests/HeadsetMediaButtonTest.java
+++ b/tests/src/com/android/server/telecom/tests/HeadsetMediaButtonTest.java
@@ -18,7 +18,6 @@
 
 import android.content.Intent;
 import android.media.session.MediaSession;
-import android.telecom.CallEndpoint;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.KeyEvent;
@@ -81,7 +80,7 @@
     }
 
     /**
-     * Nominal case; just add a call and remove it; this happens when the audio state is earpiece.
+     * Nominal case; just add a call and remove it.
      */
     @SmallTest
     @Test
@@ -91,95 +90,14 @@
         when(mMockCallsManager.hasAnyCalls()).thenReturn(true);
         mHeadsetMediaButton.onCallAdded(regularCall);
         waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
-        verify(mMediaSessionAdapter, never()).setActive(eq(true));
-
-        // Report that the endpoint is earpiece and other routes that don't matter
-        mHeadsetMediaButton.onCallEndpointChanged(
-                new CallEndpoint("Earpiece", CallEndpoint.TYPE_EARPIECE));
-        mHeadsetMediaButton.onCallEndpointChanged(
-                new CallEndpoint("Speaker", CallEndpoint.TYPE_SPEAKER));
-        mHeadsetMediaButton.onCallEndpointChanged(
-                new CallEndpoint("BT", CallEndpoint.TYPE_BLUETOOTH));
-        waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
-        verify(mMediaSessionAdapter, never()).setActive(eq(true));
-
-        // ... and thus we see how the original code isn't amenable to tests.
-        when(mMediaSessionAdapter.isActive()).thenReturn(false);
-
-        // Still should not have done anything; we never hit wired headset
-        mHeadsetMediaButton.onCallRemoved(regularCall);
-        waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
-        verify(mMediaSessionAdapter, never()).setActive(eq(false));
-    }
-
-    /**
-     * Call is added and then routed to headset after call start
-     */
-    @SmallTest
-    @Test
-    public void testAddCallThenRouteToHeadset() {
-        Call regularCall = getRegularCall();
-
-        mHeadsetMediaButton.onCallAdded(regularCall);
-        waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
-        verify(mMediaSessionAdapter, never()).setActive(eq(true));
-
-        mHeadsetMediaButton.onCallEndpointChanged(
-                new CallEndpoint("Wired Headset", CallEndpoint.TYPE_WIRED_HEADSET));
-        waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
         verify(mMediaSessionAdapter).setActive(eq(true));
-
         // ... and thus we see how the original code isn't amenable to tests.
         when(mMediaSessionAdapter.isActive()).thenReturn(true);
 
-        // Remove the one call; we should release the session.
+        when(mMockCallsManager.hasAnyCalls()).thenReturn(false);
         mHeadsetMediaButton.onCallRemoved(regularCall);
         waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
         verify(mMediaSessionAdapter).setActive(eq(false));
-        when(mMediaSessionAdapter.isActive()).thenReturn(false);
-
-        // Add a new call; make sure we go active once more.
-        mHeadsetMediaButton.onCallAdded(regularCall);
-        mHeadsetMediaButton.onCallEndpointChanged(
-                new CallEndpoint("Wired Headset", CallEndpoint.TYPE_WIRED_HEADSET));
-        waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
-        verify(mMediaSessionAdapter, times(2)).setActive(eq(true));
-    }
-
-    /**
-     * Call is added and then routed to headset after call start
-     */
-    @SmallTest
-    @Test
-    public void testAddCallThenRouteToHeadsetAndBack() {
-        Call regularCall = getRegularCall();
-
-        when(mMockCallsManager.hasAnyCalls()).thenReturn(true);
-        mHeadsetMediaButton.onCallAdded(regularCall);
-        waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
-        verify(mMediaSessionAdapter, never()).setActive(eq(true));
-
-        mHeadsetMediaButton.onCallEndpointChanged(
-                new CallEndpoint("Wired Headset", CallEndpoint.TYPE_WIRED_HEADSET));
-        waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
-        verify(mMediaSessionAdapter).setActive(eq(true));
-
-        // ... and thus we see how the original code isn't amenable to tests.
-        when(mMediaSessionAdapter.isActive()).thenReturn(true);
-
-        mHeadsetMediaButton.onCallEndpointChanged(
-                new CallEndpoint("Earpiece", CallEndpoint.TYPE_EARPIECE));
-        waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
-        verify(mMediaSessionAdapter).setActive(eq(false));
-        when(mMediaSessionAdapter.isActive()).thenReturn(false);
-
-        // Remove the one call; we should not release again.
-        mHeadsetMediaButton.onCallRemoved(regularCall);
-        waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
-        // Remember, mockito counts total invocations; we should have went active once and then
-        // inactive again when we hit earpiece.
-        verify(mMediaSessionAdapter, times(1)).setActive(eq(true));
-        verify(mMediaSessionAdapter, times(1)).setActive(eq(false));
     }
 
     /**
@@ -193,8 +111,6 @@
         // Start with a regular old call.
         when(mMockCallsManager.hasAnyCalls()).thenReturn(true);
         mHeadsetMediaButton.onCallAdded(regularCall);
-        mHeadsetMediaButton.onCallEndpointChanged(
-                new CallEndpoint("Wired Headset", CallEndpoint.TYPE_WIRED_HEADSET));
         waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
         verify(mMediaSessionAdapter).setActive(eq(true));
         when(mMediaSessionAdapter.isActive()).thenReturn(true);
@@ -206,7 +122,6 @@
         // Expect to set session inactive.
         waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
         verify(mMediaSessionAdapter).setActive(eq(false));
-        when(mMediaSessionAdapter.isActive()).thenReturn(false);
 
         // For good measure lets make it non-external again.
         when(regularCall.isExternalCall()).thenReturn(false);
@@ -214,7 +129,7 @@
         mHeadsetMediaButton.onExternalCallChanged(regularCall, false);
         // Expect to set session active.
         waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
-        verify(mMediaSessionAdapter, times(2)).setActive(eq(true));
+        verify(mMediaSessionAdapter).setActive(eq(true));
     }
 
     @MediumTest
@@ -224,8 +139,6 @@
         when(externalCall.isExternalCall()).thenReturn(true);
 
         mHeadsetMediaButton.onCallAdded(externalCall);
-        mHeadsetMediaButton.onCallEndpointChanged(
-                new CallEndpoint("Wired Headset", CallEndpoint.TYPE_WIRED_HEADSET));
         waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
         verify(mMediaSessionAdapter, never()).setActive(eq(true));
 
diff --git a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
index 16fd630..683a5e2 100644
--- a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
+++ b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
@@ -22,11 +22,13 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyObject;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.matches;
 import static org.mockito.ArgumentMatchers.nullable;
@@ -34,6 +36,7 @@
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -154,6 +157,7 @@
     @Mock private AnomalyReporterAdapter mAnomalyReporterAdapter;
     @Mock UserManager mMockUserManager;
     @Mock UserInfo mMockUserInfo;
+    @Mock UserInfo mMockChildUserInfo; //work profile
 
     @Rule
     public TestRule compatChangeRule = new PlatformCompatChangeRule();
@@ -198,13 +202,17 @@
         | Context.BIND_FOREGROUND_SERVICE | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS
         | Context.BIND_SCHEDULE_LIKE_TOP_APP;
 
+    private UserHandle mChildUserHandle = UserHandle.of(10);
+    private @Mock Call mMockChildUserCall;
+    private UserHandle mParentUserHandle = UserHandle.of(1);
+
     @Override
     @Before
     public void setUp() throws Exception {
         super.setUp();
         MockitoAnnotations.initMocks(this);
         when(mMockCall.getAnalytics()).thenReturn(new Analytics.CallInfo());
-        when(mMockCall.getUserHandleFromTargetPhoneAccount()).thenReturn(mUserHandle);
+        when(mMockCall.getAssociatedUser()).thenReturn(mUserHandle);
         when(mMockCall.getId()).thenReturn("TC@1");
         doReturn(mMockResources).when(mMockContext).getResources();
         doReturn(mMockAppOpsManager).when(mMockContext).getSystemService(AppOpsManager.class);
@@ -233,8 +241,8 @@
         doAnswer(invocation -> {
             mRegisteredReceiver = invocation.getArgument(0);
             return null;
-        }).when(mMockContext).registerReceiver(any(BroadcastReceiver.class),
-                any(IntentFilter.class));
+        }).when(mMockContext).registerReceiverAsUser(any(BroadcastReceiver.class),
+                any(), any(IntentFilter.class), any(), any());
 
         ArgumentCaptor<SystemStateHelper.SystemStateListener> systemStateListenerArgumentCaptor
                 = ArgumentCaptor.forClass(SystemStateHelper.SystemStateListener.class);
@@ -296,6 +304,8 @@
         when(mMockCallsManager.getAudioState()).thenReturn(new CallAudioState(false, 0, 0));
 
         when(mMockContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mMockUserManager);
+        when(mMockContext.getSystemService(eq(UserManager.class)))
+                .thenReturn(mMockUserManager);
         // Mock user info to allow binding on user stored in the phone account (mUserHandle).
         when(mMockUserManager.getUserInfo(anyInt())).thenReturn(mMockUserInfo);
         when(mMockUserInfo.isManagedProfile()).thenReturn(true);
@@ -414,6 +424,7 @@
         when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
         when(mMockCallsManager.isInEmergencyCall()).thenReturn(false);
         when(mMockCall.isIncoming()).thenReturn(false);
+        when(mMockCall.getAssociatedUser()).thenReturn(mUserHandle);
         when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
         when(mMockCall.getIntentExtras()).thenReturn(callExtras);
         when(mMockCall.isExternalCall()).thenReturn(false);
@@ -451,6 +462,7 @@
         when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
         when(mMockCallsManager.isInEmergencyCall()).thenReturn(false);
         when(mMockCall.isIncoming()).thenReturn(false);
+        when(mMockCall.getAssociatedUser()).thenReturn(mUserHandle);
         when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
         when(mMockCall.getIntentExtras()).thenReturn(callExtras);
         when(mMockCall.isExternalCall()).thenReturn(false);
@@ -507,6 +519,7 @@
             .thenReturn(mMockUserManager);
         when(mMockUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(false);
         when(mMockCall.isIncoming()).thenReturn(false);
+        when(mMockCall.getAssociatedUser()).thenReturn(mUserHandle);
         when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
         when(mMockCall.getIntentExtras()).thenReturn(callExtras);
         when(mMockCall.isExternalCall()).thenReturn(false);
@@ -573,7 +586,8 @@
         when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
         when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
         when(mMockCall.isEmergencyCall()).thenReturn(true);
-        when(mMockCall.getUserHandleFromTargetPhoneAccount()).thenReturn(DUMMY_USER_HANDLE);
+        when(mMockCall.isIncoming()).thenReturn(true);
+        when(mMockCall.getAssociatedUser()).thenReturn(DUMMY_USER_HANDLE);
         when(mMockContext.getSystemService(eq(UserManager.class)))
             .thenReturn(mMockUserManager);
         when(mMockUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(true);
@@ -601,7 +615,8 @@
         when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
         when(mMockCall.isEmergencyCall()).thenReturn(false);
         when(mMockCall.isInECBM()).thenReturn(true);
-        when(mMockCall.getUserHandleFromTargetPhoneAccount()).thenReturn(DUMMY_USER_HANDLE);
+        when(mMockCall.isIncoming()).thenReturn(true);
+        when(mMockCall.getAssociatedUser()).thenReturn(DUMMY_USER_HANDLE);
         when(mMockContext.getSystemService(eq(UserManager.class)))
                 .thenReturn(mMockUserManager);
         when(mMockUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(true);
@@ -623,15 +638,47 @@
     @MediumTest
     @Test
     public void
+    testBindToService_UserAssociatedWithCallSecondary_NonEmergCallECBM_BindsToSecondaryUser()
+            throws Exception {
+        UserHandle newUser = new UserHandle(13);
+        when(mMockCallsManager.getCurrentUserHandle()).thenReturn(newUser);
+        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+        when(mMockCall.isEmergencyCall()).thenReturn(false);
+        when(mMockCall.isInECBM()).thenReturn(true);
+        when(mMockCall.isIncoming()).thenReturn(true);
+        when(mMockCall.getAssociatedUser()).thenReturn(DUMMY_USER_HANDLE);
+        when(mMockContext.getSystemService(eq(UserManager.class)))
+                .thenReturn(mMockUserManager);
+        when(mMockUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(false);
+        when(mMockUserManager.isUserAdmin(anyInt())).thenReturn(false);
+        setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
+        setupMockPackageManagerLocationPermission(SYS_PKG, false /* granted */);
+
+        mInCallController.bindToServices(mMockCall);
+
+        ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mMockContext, times(1)).bindServiceAsUser(
+                bindIntentCaptor.capture(),
+                any(ServiceConnection.class),
+                eq(serviceBindingFlags),
+                eq(newUser));
+        Intent bindIntent = bindIntentCaptor.getValue();
+        assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
+    }
+
+    @MediumTest
+    @Test
+    public void
     testBindToService_UserAssociatedWithCallNotInQuietMode_EmergCallInCallUi_BindsToAssociatedUser()
         throws Exception {
         when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
         when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
         when(mMockCall.isEmergencyCall()).thenReturn(true);
-        when(mMockCall.getUserHandleFromTargetPhoneAccount()).thenReturn(DUMMY_USER_HANDLE);
+        when(mMockCall.getAssociatedUser()).thenReturn(DUMMY_USER_HANDLE);
         when(mMockContext.getSystemService(eq(UserManager.class)))
             .thenReturn(mMockUserManager);
         when(mMockUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(false);
+        when(mMockUserManager.isUserAdmin(anyInt())).thenReturn(true);
         setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
         setupMockPackageManagerLocationPermission(SYS_PKG, false /* granted */);
 
@@ -667,6 +714,7 @@
             .thenReturn(mMockUserManager);
         when(mMockUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(false);
         when(mMockCall.isIncoming()).thenReturn(false);
+        when(mMockCall.getAssociatedUser()).thenReturn(mUserHandle);
         when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
         when(mMockCall.getIntentExtras()).thenReturn(callExtras);
         when(mMockCall.isExternalCall()).thenReturn(false);
@@ -753,6 +801,7 @@
         when(mMockCallsManager.getAudioState()).thenReturn(null);
         when(mMockCallsManager.canAddCall()).thenReturn(false);
         when(mMockCall.isIncoming()).thenReturn(false);
+        when(mMockCall.getAssociatedUser()).thenReturn(mUserHandle);
         when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
         when(mMockCall.getIntentExtras()).thenReturn(callExtras);
         when(mMockCall.isExternalCall()).thenReturn(false);
@@ -833,6 +882,7 @@
         when(mMockCallsManager.isInEmergencyCall()).thenReturn(false);
         when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
         when(mMockCall.isIncoming()).thenReturn(false);
+        when(mMockCall.getAssociatedUser()).thenReturn(mUserHandle);
         when(mMockCall.isExternalCall()).thenReturn(false);
         when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
         when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
@@ -945,6 +995,7 @@
         when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
         when(mMockCall.getIntentExtras()).thenReturn(callExtras);
         when(mMockCall.isExternalCall()).thenReturn(false);
+        when(mMockCall.getAssociatedUser()).thenReturn(mUserHandle);
         when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID))
                 .thenReturn(DEF_PKG);
         ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
@@ -1051,6 +1102,7 @@
                 .thenReturn(mMockUserManager);
         when(mMockUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(false);
         when(mMockCall.isIncoming()).thenReturn(false);
+        when(mMockCall.getAssociatedUser()).thenReturn(mUserHandle);
         when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
         when(mMockCall.getIntentExtras()).thenReturn(callExtras);
         when(mMockCall.isExternalCall()).thenReturn(false);
@@ -1502,6 +1554,7 @@
         when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
         when(mMockCallsManager.isInEmergencyCall()).thenReturn(false);
         when(mMockCall.isIncoming()).thenReturn(false);
+        when(mMockCall.getAssociatedUser()).thenReturn(mUserHandle);
         when(mMockCall.isExternalCall()).thenReturn(false);
         when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
         when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID)).thenReturn(DEF_PKG);
@@ -1736,6 +1789,118 @@
                 eq(UserHandle.CURRENT));
     }
 
+    @Test
+    public void testGetUserFromCall_TargetPhoneAccountNotSet() throws Exception {
+        setupMocks(false /* isExternalCall */);
+        setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
+        UserHandle testUser = new UserHandle(10);
+
+        when(mMockCall.getTargetPhoneAccount()).thenReturn(null);
+        when(mMockCall.getAssociatedUser()).thenReturn(testUser);
+
+        // Bind to ICS. The mapping should've been inserted with the testUser as the key.
+        mInCallController.bindToServices(mMockCall);
+        assertTrue(mInCallController.getInCallServiceConnections().containsKey(testUser));
+
+        // Set the target phone account. Simulates the flow when the user has chosen which sim to
+        // place the call on.
+        when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
+
+        // Remove the call. This invokes getUserFromCall to remove the ICS mapping.
+        when(mMockCallsManager.getCalls()).thenReturn(Collections.emptyList());
+        mInCallController.onCallRemoved(mMockCall);
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
+
+        // Verify that the mapping was properly removed.
+        assertNull(mInCallController.getInCallServiceConnections().get(testUser));
+    }
+
+    @Test
+    public void testGetUserFromCall_IncomingCall() throws Exception {
+        setupMocks(false /* isExternalCall */);
+        setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
+        // Explicitly test on a different user to avoid interference with current user.
+        UserHandle testUser = new UserHandle(10);
+
+        // Set user handle in target phone account to test user
+        when(mMockCall.getAssociatedUser()).thenReturn(testUser);
+        when(mMockCall.isIncoming()).thenReturn(true);
+
+        // Bind to ICS. The mapping should've been inserted with the testUser as the key.
+        mInCallController.bindToServices(mMockCall);
+        assertTrue(mInCallController.getInCallServiceConnections().containsKey(testUser));
+
+        // Remove the call. This invokes getUserFromCall to remove the ICS mapping.
+        when(mMockCallsManager.getCalls()).thenReturn(Collections.emptyList());
+        mInCallController.onCallRemoved(mMockCall);
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
+
+        // Verify that the mapping was properly removed.
+        assertNull(mInCallController.getInCallServiceConnections().get(testUser));
+    }
+
+    private void setupMocksForWorkProfileTest() {
+        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+        when(mMockCallsManager.isInEmergencyCall()).thenReturn(false);
+        when(mMockChildUserCall.isIncoming()).thenReturn(false);
+        when(mMockChildUserCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
+        when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID)).thenReturn(DEF_PKG);
+        when(mMockContext.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
+                anyInt(), any())).thenReturn(true);
+        when(mMockChildUserCall.isExternalCall()).thenReturn(false);
+        when(mMockChildUserCall.isSelfManaged()).thenReturn(true);
+        when(mMockChildUserCall.visibleToInCallService()).thenReturn(true);
+
+        //Setup up parent and child/work profile relation
+        when(mMockUserInfo.getUserHandle()).thenReturn(mParentUserHandle);
+        when(mMockChildUserInfo.getUserHandle()).thenReturn(mChildUserHandle);
+        when(mMockUserInfo.isManagedProfile()).thenReturn(false);
+        when(mMockChildUserInfo.isManagedProfile()).thenReturn(true);
+        when(mMockChildUserCall.getAssociatedUser()).thenReturn(mChildUserHandle);
+        when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mChildUserHandle);
+        when(mMockUserManager.getProfileParent(mChildUserHandle.getIdentifier())).thenReturn(
+                mMockUserInfo);
+        when(mMockUserManager.getProfileParent(mChildUserHandle)).thenReturn(mParentUserHandle);
+        when(mMockUserManager.getUserInfo(eq(mParentUserHandle.getIdentifier()))).thenReturn(
+                mMockUserInfo);
+        when(mMockUserManager.getUserInfo(eq(mChildUserHandle.getIdentifier()))).thenReturn(
+                mMockChildUserInfo);
+        when(mMockUserManager.isManagedProfile(mChildUserHandle.getIdentifier())).thenReturn(true);
+        when(mMockUserManager.isManagedProfile(mParentUserHandle.getIdentifier())).thenReturn(
+                false);
+    }
+
+    @Test
+    public void testManagedProfileCallQueriesIcsUsingParentUserToo() throws Exception {
+        setupMocksForWorkProfileTest();
+        setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
+        setupMockPackageManager(true /* default */,
+                true /*useNonUiInCalls*/, true /*useAppOpNonUiInCalls*/,
+                true /*useSystemDialer*/, false /*includeExternalCalls*/,
+                true /*includeSelfManagedCallsInDefaultDialer*/,
+                true /*includeSelfManagedCallsInCarModeDialer*/,
+                true /*includeSelfManagedCallsInNonUi*/);
+
+        //pass in call by child/work-profileuser
+        mInCallController.bindToServices(mMockChildUserCall);
+
+        // Verify that queryIntentServicesAsUser is also called with parent handle
+        // Query for the different InCallServices
+        ArgumentCaptor<Integer> userIdCaptor = ArgumentCaptor.forClass(Integer.class);
+        ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+        ArgumentCaptor<Integer> flagCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mMockPackageManager, times(6)).queryIntentServicesAsUser(
+                queryIntentCaptor.capture(), flagCaptor.capture(), userIdCaptor.capture());
+        List<Integer> userIds = userIdCaptor.getAllValues();
+
+        //check if queryIntentServices was called with child user handle
+        assertTrue("no query parent user handle",
+                userIds.contains(mChildUserHandle.getIdentifier()));
+        //check if queryIntentServices was also called with parent user handle
+        assertTrue("no query parent user handle",
+                userIds.contains(mParentUserHandle.getIdentifier()));
+    }
+
     private void setupMocks(boolean isExternalCall) {
         setupMocks(isExternalCall, false /* isSelfManagedCall */);
     }
@@ -1745,6 +1910,7 @@
         when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
         when(mMockCallsManager.isInEmergencyCall()).thenReturn(false);
         when(mMockCall.isIncoming()).thenReturn(false);
+        when(mMockCall.getAssociatedUser()).thenReturn(mUserHandle);
         when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
         when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID)).thenReturn(DEF_PKG);
         when(mMockContext.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
diff --git a/tests/src/com/android/server/telecom/tests/IncomingCallNotifierTest.java b/tests/src/com/android/server/telecom/tests/IncomingCallNotifierTest.java
index a38de94..914fdc5 100644
--- a/tests/src/com/android/server/telecom/tests/IncomingCallNotifierTest.java
+++ b/tests/src/com/android/server/telecom/tests/IncomingCallNotifierTest.java
@@ -75,7 +75,7 @@
 
         when(mAudioCall.getVideoState()).thenReturn(VideoProfile.STATE_AUDIO_ONLY);
         when(mAudioCall.getTargetPhoneAccountLabel()).thenReturn("Bar");
-        when(mAudioCall.getUserHandleFromTargetPhoneAccount()).
+        when(mAudioCall.getAssociatedUser()).
                 thenReturn(UserHandle.CURRENT);
         when(mVideoCall.getVideoState()).thenReturn(VideoProfile.STATE_BIDIRECTIONAL);
         when(mVideoCall.getTargetPhoneAccountLabel()).thenReturn("Bar");
@@ -84,7 +84,7 @@
         when(mRingingCall.getState()).thenReturn(CallState.RINGING);
         when(mRingingCall.getVideoState()).thenReturn(VideoProfile.STATE_AUDIO_ONLY);
         when(mRingingCall.getTargetPhoneAccountLabel()).thenReturn("Foo");
-        when(mRingingCall.getUserHandleFromTargetPhoneAccount()).
+        when(mRingingCall.getAssociatedUser()).
                 thenReturn(UserHandle.CURRENT);
         when(mRingingCall.getHandoverState()).thenReturn(HandoverState.HANDOVER_NONE);
     }
diff --git a/tests/src/com/android/server/telecom/tests/MissedInformationTest.java b/tests/src/com/android/server/telecom/tests/MissedInformationTest.java
index 8ea2739..4af3de3 100644
--- a/tests/src/com/android/server/telecom/tests/MissedInformationTest.java
+++ b/tests/src/com/android/server/telecom/tests/MissedInformationTest.java
@@ -150,7 +150,7 @@
     public void testEmergencyCallPlacing() throws Exception {
         Analytics.dumpToParcelableAnalytics();
         setUpEmergencyCall();
-        when(mEmergencyCall.getUserHandleFromTargetPhoneAccount()).
+        when(mEmergencyCall.getAssociatedUser()).
                 thenReturn(mPhoneAccountA0.getAccountHandle().getUserHandle());
         mCallsManager.addCall(mEmergencyCall);
         assertTrue(mCallsManager.isInEmergencyCall());
diff --git a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
index f2bcf18..33acd98 100644
--- a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
+++ b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
@@ -101,7 +101,7 @@
     @Before
     public void setUp() throws Exception {
         super.setUp();
-        when(mCall.getInitiatingUser()).thenReturn(UserHandle.CURRENT);
+        when(mCall.getAssociatedUser()).thenReturn(UserHandle.CURRENT);
         when(mCallsManager.getLock()).thenReturn(new TelecomSystem.SyncRoot() { });
         when(mCallsManager.getSystemStateHelper()).thenReturn(mSystemStateHelper);
         when(mCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
diff --git a/tests/src/com/android/server/telecom/tests/RingerTest.java b/tests/src/com/android/server/telecom/tests/RingerTest.java
index a02415c..a4adf77 100644
--- a/tests/src/com/android/server/telecom/tests/RingerTest.java
+++ b/tests/src/com/android/server/telecom/tests/RingerTest.java
@@ -123,8 +123,8 @@
         when(mockRingtoneFactory.hasHapticChannels(any(Ringtone.class))).thenReturn(false);
         when(mockCall1.getState()).thenReturn(CallState.RINGING);
         when(mockCall2.getState()).thenReturn(CallState.RINGING);
-        when(mockCall1.getUserHandleFromTargetPhoneAccount()).thenReturn(PA_HANDLE.getUserHandle());
-        when(mockCall2.getUserHandleFromTargetPhoneAccount()).thenReturn(PA_HANDLE.getUserHandle());
+        when(mockCall1.getAssociatedUser()).thenReturn(PA_HANDLE.getUserHandle());
+        when(mockCall2.getAssociatedUser()).thenReturn(PA_HANDLE.getUserHandle());
 
         createRingerUnderTest();
     }
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index d013fae..b962b2a 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -428,12 +428,13 @@
         super.tearDown();
     }
 
-    protected ParcelableCall makeConferenceCall() throws Exception {
-        IdPair callId1 = startAndMakeActiveOutgoingCall("650-555-1212",
-                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+    protected ParcelableCall makeConferenceCall(
+            Intent callIntentExtras1, Intent callIntentExtras2) throws Exception {
+        IdPair callId1 = startAndMakeActiveOutgoingCallWithExtras("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, callIntentExtras1);
 
-        IdPair callId2 = startAndMakeActiveOutgoingCall("650-555-1213",
-                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+        IdPair callId2 = startAndMakeActiveOutgoingCallWithExtras("650-555-1213",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, callIntentExtras2);
 
         IInCallAdapter inCallAdapter = mInCallServiceFixtureX.getInCallAdapter();
         inCallAdapter.conference(callId1.mCallId, callId2.mCallId);
@@ -640,7 +641,7 @@
 
         startOutgoingPhoneCallWaitForBroadcaster(number, null,
                 connectionServiceFixture, Process.myUserHandle(), VideoProfile.STATE_AUDIO_ONLY,
-                false /*isEmergency*/);
+                false /*isEmergency*/, null);
 
         return mInCallServiceFixtureX.mLatestCallId;
     }
@@ -670,17 +671,17 @@
             throws Exception {
 
         return startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
-                initiatingUser, VideoProfile.STATE_AUDIO_ONLY);
+                initiatingUser, VideoProfile.STATE_AUDIO_ONLY, null);
     }
 
     protected IdPair startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle,
             ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
-            int videoState) throws Exception {
+            int videoState, Intent callIntentExtras) throws Exception {
         int startingNumConnections = connectionServiceFixture.mConnectionById.size();
         int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
 
         startOutgoingPhoneCallPendingCreateConnection(number, phoneAccountHandle,
-                connectionServiceFixture, initiatingUser, videoState);
+                connectionServiceFixture, initiatingUser, videoState, callIntentExtras);
 
         verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
                 .createConnectionComplete(anyString(), any());
@@ -723,7 +724,7 @@
 
         // Call will not use the ordered broadcaster, since it is an Emergency Call
         startOutgoingPhoneCallWaitForBroadcaster(number, phoneAccountHandle,
-                connectionServiceFixture, initiatingUser, videoState, true /*isEmergency*/);
+                connectionServiceFixture, initiatingUser, videoState, true /*isEmergency*/, null);
 
         return outgoingCallCreateConnectionComplete(startingNumConnections, startingNumCalls,
                 phoneAccountHandle, connectionServiceFixture);
@@ -732,7 +733,7 @@
     protected void startOutgoingPhoneCallWaitForBroadcaster(String number,
             PhoneAccountHandle phoneAccountHandle,
             ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
-            int videoState, boolean isEmergency) throws Exception {
+            int videoState, boolean isEmergency, Intent actionCallIntent) throws Exception {
         reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(),
                 mInCallServiceFixtureY.getTestDouble());
 
@@ -745,7 +746,9 @@
 
         boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null;
 
-        Intent actionCallIntent = new Intent();
+        if (actionCallIntent == null) {
+            actionCallIntent = new Intent();
+        }
         actionCallIntent.setData(Uri.parse("tel:" + number));
         actionCallIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
         if(isEmergency) {
@@ -790,9 +793,10 @@
     protected String startOutgoingPhoneCallPendingCreateConnection(String number,
             PhoneAccountHandle phoneAccountHandle,
             ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
-            int videoState) throws Exception {
+            int videoState, Intent callIntentExtras) throws Exception {
         startOutgoingPhoneCallWaitForBroadcaster(number,phoneAccountHandle,
-                connectionServiceFixture, initiatingUser, videoState, false /*isEmergency*/);
+                connectionServiceFixture, initiatingUser,
+                videoState, false /*isEmergency*/, callIntentExtras);
         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
 
         verifyAndProcessOutgoingCallBroadcast(phoneAccountHandle);
@@ -897,14 +901,24 @@
             PhoneAccountHandle phoneAccountHandle,
             final ConnectionServiceFixture connectionServiceFixture) throws Exception {
         return startIncomingPhoneCall(number, phoneAccountHandle, VideoProfile.STATE_AUDIO_ONLY,
-                connectionServiceFixture);
+                connectionServiceFixture, null);
+    }
+
+    protected IdPair startIncomingPhoneCallWithExtras(
+            String number,
+            PhoneAccountHandle phoneAccountHandle,
+            final ConnectionServiceFixture connectionServiceFixture,
+            Bundle extras) throws Exception {
+        return startIncomingPhoneCall(number, phoneAccountHandle, VideoProfile.STATE_AUDIO_ONLY,
+                connectionServiceFixture, extras);
     }
 
     protected IdPair startIncomingPhoneCall(
             String number,
             PhoneAccountHandle phoneAccountHandle,
             int videoState,
-            final ConnectionServiceFixture connectionServiceFixture) throws Exception {
+            final ConnectionServiceFixture connectionServiceFixture,
+            Bundle extras) throws Exception {
         reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(),
                 mInCallServiceFixtureY.getTestDouble());
 
@@ -921,7 +935,9 @@
                 new IncomingCallAddedListener(incomingCallAddedLatch);
         mTelecomSystem.getCallsManager().addListener(callAddedListener);
 
-        Bundle extras = new Bundle();
+        if (extras == null) {
+            extras = new Bundle();
+        }
         extras.putParcelable(
                 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
                 Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null));
@@ -1012,7 +1028,16 @@
             PhoneAccountHandle phoneAccountHandle,
             ConnectionServiceFixture connectionServiceFixture) throws Exception {
         return startAndMakeActiveOutgoingCall(number, phoneAccountHandle, connectionServiceFixture,
-                VideoProfile.STATE_AUDIO_ONLY);
+                VideoProfile.STATE_AUDIO_ONLY, null);
+    }
+
+    protected IdPair startAndMakeActiveOutgoingCallWithExtras(
+            String number,
+            PhoneAccountHandle phoneAccountHandle,
+            ConnectionServiceFixture connectionServiceFixture,
+            Intent callIntentExtras) throws Exception {
+        return startAndMakeActiveOutgoingCall(number, phoneAccountHandle, connectionServiceFixture,
+                VideoProfile.STATE_AUDIO_ONLY, callIntentExtras);
     }
 
     // A simple outgoing call, verifying that the appropriate connection service is contacted,
@@ -1020,9 +1045,10 @@
     protected IdPair startAndMakeActiveOutgoingCall(
             String number,
             PhoneAccountHandle phoneAccountHandle,
-            ConnectionServiceFixture connectionServiceFixture, int videoState) throws Exception {
+            ConnectionServiceFixture connectionServiceFixture, int videoState,
+            Intent callIntentExtras) throws Exception {
         IdPair ids = startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
-                Process.myUserHandle(), videoState);
+                Process.myUserHandle(), videoState, callIntentExtras);
 
         connectionServiceFixture.sendSetDialing(ids.mConnectionId);
         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
@@ -1131,7 +1157,7 @@
             PhoneAccountHandle phoneAccountHandle,
             ConnectionServiceFixture connectionServiceFixture) throws Exception {
         IdPair ids = startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
-                Process.myUserHandle(), VideoProfile.STATE_AUDIO_ONLY);
+                Process.myUserHandle(), VideoProfile.STATE_AUDIO_ONLY, null);
 
         connectionServiceFixture.sendSetDialing(ids.mConnectionId);
         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
diff --git a/tests/src/com/android/server/telecom/tests/TransactionalServiceWrapperTest.java b/tests/src/com/android/server/telecom/tests/TransactionalServiceWrapperTest.java
index 98624d4..fa5f2a2 100644
--- a/tests/src/com/android/server/telecom/tests/TransactionalServiceWrapperTest.java
+++ b/tests/src/com/android/server/telecom/tests/TransactionalServiceWrapperTest.java
@@ -25,6 +25,7 @@
 
 
 import android.content.ComponentName;
+import android.os.IBinder;
 import android.os.OutcomeReceiver;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -69,6 +70,7 @@
     @Mock private TransactionManager mTransactionManager;
     @Mock private ICallEventCallback mCallEventCallback;
     @Mock private TransactionalServiceRepository mRepository;
+    @Mock private IBinder mIBinder;
     private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() {};
 
     @Override
@@ -79,7 +81,7 @@
         Mockito.when(mMockCall1.getId()).thenReturn(CALL_ID_1);
         Mockito.when(mMockCall2.getId()).thenReturn(CALL_ID_2);
         Mockito.when(mCallsManager.getLock()).thenReturn(mLock);
-
+        Mockito.when(mCallEventCallback.asBinder()).thenReturn(mIBinder);
         mTransactionalServiceWrapper = new TransactionalServiceWrapper(mCallEventCallback,
                 mCallsManager, SERVICE_HANDLE, mMockCall1, mRepository);
 
diff --git a/tests/src/com/android/server/telecom/tests/VideoCallTests.java b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
index 97e71d1..84beedc 100644
--- a/tests/src/com/android/server/telecom/tests/VideoCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
@@ -105,7 +105,7 @@
         // Start an incoming video call.
         IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
-                VideoProfile.STATE_BIDIRECTIONAL);
+                VideoProfile.STATE_BIDIRECTIONAL, null);
 
         verifyAudioRoute(CallAudioState.ROUTE_SPEAKER);
     }
@@ -121,7 +121,7 @@
         // Start an incoming video call.
         IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
-                VideoProfile.STATE_TX_ENABLED);
+                VideoProfile.STATE_TX_ENABLED, null);
 
         verifyAudioRoute(CallAudioState.ROUTE_SPEAKER);
     }
@@ -137,7 +137,7 @@
         // Start an incoming video call.
         IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
-                VideoProfile.STATE_AUDIO_ONLY);
+                VideoProfile.STATE_AUDIO_ONLY, null);
 
         verifyAudioRoute(CallAudioState.ROUTE_EARPIECE);
     }
@@ -165,7 +165,7 @@
     @Test
     public void testIncomingVideoCallMissedCheckVideoHistory() throws Exception {
         IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
-                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
         com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
                 .iterator().next();
 
@@ -182,7 +182,7 @@
     @Test
     public void testIncomingVideoCallRejectedCheckVideoHistory() throws Exception {
         IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
-                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
         com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
                 .iterator().next();
 
@@ -201,7 +201,7 @@
     public void testOutgoingVideoCallCanceledCheckVideoHistory() throws Exception {
         IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
                 mConnectionServiceFixtureA, Process.myUserHandle(),
-                VideoProfile.STATE_BIDIRECTIONAL);
+                VideoProfile.STATE_BIDIRECTIONAL, null);
         com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
                 .iterator().next();
 
@@ -219,7 +219,7 @@
     public void testOutgoingVideoCallRejectedCheckVideoHistory() throws Exception {
         IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
                 mConnectionServiceFixtureA, Process.myUserHandle(),
-                VideoProfile.STATE_BIDIRECTIONAL);
+                VideoProfile.STATE_BIDIRECTIONAL, null);
         com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
                 .iterator().next();
 
@@ -237,7 +237,7 @@
     public void testOutgoingVideoCallAnsweredAsAudio() throws Exception {
         IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
                 mConnectionServiceFixtureA, Process.myUserHandle(),
-                VideoProfile.STATE_BIDIRECTIONAL);
+                VideoProfile.STATE_BIDIRECTIONAL, null);
         com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
                 .iterator().next();
 
diff --git a/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java b/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java
index c9ea34f..c66b0f7 100644
--- a/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java
+++ b/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java
@@ -18,30 +18,30 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManagerInternal;
 import android.app.ForegroundServiceDelegationOptions;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.app.Person;
 import android.content.ComponentName;
+import android.content.Intent;
 import android.content.ServiceConnection;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.UserHandle;
-import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
 import android.telecom.PhoneAccountHandle;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.server.telecom.Call;
-import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.CallState;
 import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.voip.VoipCallMonitor;
 
@@ -55,16 +55,18 @@
 @RunWith(JUnit4.class)
 public class VoipCallMonitorTest extends TelecomTestCase {
     private VoipCallMonitor mMonitor;
+    private static final String NAME = "John Smith";
     private static final String PKG_NAME_1 = "telecom.voip.test1";
     private static final String PKG_NAME_2 = "telecom.voip.test2";
     private static final String CLS_NAME = "VoipActivity";
     private static final String ID_1 = "id1";
+    public static final String CHANNEL_ID = "TelecomVoipAppChannelId";
     private static final UserHandle USER_HANDLE_1 = new UserHandle(1);
     private static final long TIMEOUT = 5000L;
 
     @Mock private TelecomSystem.SyncRoot mLock;
     @Mock private ActivityManagerInternal mActivityManagerInternal;
-    @Mock private NotificationListenerService mListenerService;
+    @Mock private IBinder mServiceConnection;
 
     private final PhoneAccountHandle mHandle1User1 = new PhoneAccountHandle(
             new ComponentName(PKG_NAME_1, CLS_NAME), ID_1, USER_HANDLE_1);
@@ -77,12 +79,11 @@
         super.setUp();
         mMonitor = new VoipCallMonitor(mContext, mLock);
         mActivityManagerInternal = mock(ActivityManagerInternal.class);
-        mListenerService = mock(NotificationListenerService.class);
         mMonitor.setActivityManagerInternal(mActivityManagerInternal);
-        mMonitor.setNotificationListenerService(mListenerService);
-        doNothing().when(mListenerService).registerAsSystemService(eq(mContext),
-                any(ComponentName.class), anyInt());
         mMonitor.startMonitor();
+        when(mActivityManagerInternal.startForegroundServiceDelegate(any(
+                ForegroundServiceDelegationOptions.class), any(ServiceConnection.class)))
+                .thenReturn(true);
     }
 
     @SmallTest
@@ -206,13 +207,98 @@
                 .stopForegroundServiceDelegate(any(ServiceConnection.class));
     }
 
+    /**
+     * Ensure an app loses foreground service delegation if the user dismisses the call style
+     * notification or the app removes the notification.
+     * Note: post the notification AFTER foreground service delegation is gained
+     */
+    @SmallTest
+    @Test
+    public void testStopFgsIfCallNotificationIsRemoved_PostedAfterFgsIsGained() {
+        // GIVEN
+        StatusBarNotification sbn = createStatusBarNotificationFromHandle(mHandle1User1);
+
+        // WHEN
+        // FGS is gained after the call is added to VoipCallMonitor
+        ServiceConnection c = addCallAndVerifyFgsIsGained(createTestCall("1", mHandle1User1));
+        // simulate an app posting a call style notification after FGS is gained
+        mMonitor.postNotification(sbn);
+
+        // THEN
+        // shortly after posting the notification, simulate the user dismissing it
+        mMonitor.removeNotification(sbn);
+        // FGS should be removed once the notification is removed
+        verify(mActivityManagerInternal, timeout(TIMEOUT)).stopForegroundServiceDelegate(c);
+    }
+
+    /**
+     * Ensure an app loses foreground service delegation if the user dismisses the call style
+     * notification or the app removes the notification.
+     * Note: post the notification BEFORE foreground service delegation is gained
+     */
+    @SmallTest
+    @Test
+    public void testStopFgsIfCallNotificationIsRemoved_PostedBeforeFgsIsGained() {
+        // GIVEN
+        StatusBarNotification sbn = createStatusBarNotificationFromHandle(mHandle1User1);
+
+        // WHEN
+        //  an app posts a call style notification before FGS is gained
+        mMonitor.postNotification(sbn);
+        // FGS is gained after the call is added to VoipCallMonitor
+        ServiceConnection c = addCallAndVerifyFgsIsGained(createTestCall("1", mHandle1User1));
+
+        // THEN
+        // shortly after posting the notification, simulate the user dismissing it
+        mMonitor.removeNotification(sbn);
+        // FGS should be removed once the notification is removed
+        verify(mActivityManagerInternal, timeout(TIMEOUT)).stopForegroundServiceDelegate(c);
+    }
+
     private Call createTestCall(String id, PhoneAccountHandle handle) {
         Call call = mock(Call.class);
         when(call.getTargetPhoneAccount()).thenReturn(handle);
         when(call.isTransactionalCall()).thenReturn(true);
         when(call.getExtras()).thenReturn(new Bundle());
         when(call.getId()).thenReturn(id);
-        when(call.getCallingPackageIdentity()).thenReturn( new Call.CallingPackageIdentity() );
+        when(call.getCallingPackageIdentity()).thenReturn(new Call.CallingPackageIdentity());
+        when(call.getState()).thenReturn(CallState.ACTIVE);
         return call;
     }
+
+    private Notification createCallStyleNotification() {
+        PendingIntent pendingOngoingIntent = PendingIntent.getActivity(mContext, 0,
+                new Intent(""), PendingIntent.FLAG_IMMUTABLE);
+
+        return new Notification.Builder(mContext,
+                CHANNEL_ID)
+                .setStyle(Notification.CallStyle.forOngoingCall(
+                        new Person.Builder().setName(NAME).setImportant(true).build(),
+                        pendingOngoingIntent)
+                )
+                .setFullScreenIntent(pendingOngoingIntent, true)
+                .build();
+    }
+
+    private StatusBarNotification createStatusBarNotificationFromHandle(PhoneAccountHandle handle) {
+        return new StatusBarNotification(
+                handle.getComponentName().getPackageName(), "", 0, "", 0, 0,
+                createCallStyleNotification(), handle.getUserHandle(), "", 0);
+    }
+
+    private ServiceConnection addCallAndVerifyFgsIsGained(Call call) {
+        ArgumentCaptor<ServiceConnection> captor = ArgumentCaptor.forClass(ServiceConnection.class);
+        // add the call to the VoipCallMonitor under test which will start FGS
+        mMonitor.onCallAdded(call);
+        // FGS should be granted within the timeout
+        verify(mActivityManagerInternal, timeout(TIMEOUT))
+                .startForegroundServiceDelegate(any(
+                                ForegroundServiceDelegationOptions.class),
+                        captor.capture());
+        // onServiceConnected must be called in order for VoipCallMonitor to start monitoring for
+        // a notification before the timeout expires
+        ServiceConnection serviceConnection = captor.getValue();
+        serviceConnection.onServiceConnected(mHandle1User1.getComponentName(), mServiceConnection);
+        return serviceConnection;
+    }
 }