Loading flags/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ aconfig_declarations { "telecom_calllog_flags.aconfig", "telecom_resolve_hidden_dependencies.aconfig", "telecom_bluetoothroutemanager_flags.aconfig", "telecom_work_profile_flags.aconfig" ], } flags/telecom_work_profile_flags.aconfig 0 → 100644 +8 −0 Original line number Diff line number Diff line package: "com.android.server.telecom.flags" flag { name: "work_profile_associated_user" namespace: "telecom" description: "Redefines the associated user for calls in the context of work profile support (U+)" bug: "294699269" } No newline at end of file src/com/android/server/telecom/Call.java +21 −8 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ import android.widget.Toast; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telecom.IVideoProvider; import com.android.internal.util.Preconditions; import com.android.server.telecom.flags.FeatureFlags; import com.android.server.telecom.stats.CallFailureCause; import com.android.server.telecom.stats.CallStateChangedAtomWriter; import com.android.server.telecom.ui.ToastFactory; Loading Loading @@ -788,6 +789,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, */ private CompletableFuture<Boolean> mDisconnectFuture; private FeatureFlags mFlags; /** * Persists the specified parameters and initializes the new instance. * @param context The context. Loading Loading @@ -819,11 +822,12 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, boolean shouldAttachToExistingConnection, boolean isConference, ClockProxy clockProxy, ToastFactory toastFactory) { ToastFactory toastFactory, FeatureFlags featureFlags) { this(callId, context, callsManager, lock, repository, phoneNumberUtilsAdapter, handle, null, gatewayInfo, connectionManagerPhoneAccountHandle, targetPhoneAccountHandle, callDirection, shouldAttachToExistingConnection, isConference, clockProxy, toastFactory); isConference, clockProxy, toastFactory, featureFlags); } Loading @@ -843,8 +847,10 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, boolean shouldAttachToExistingConnection, boolean isConference, ClockProxy clockProxy, ToastFactory toastFactory) { ToastFactory toastFactory, FeatureFlags featureFlags) { mFlags = featureFlags; mId = callId; mConnectionId = callId; mState = (isConference && callDirection != CALL_DIRECTION_INCOMING && Loading Loading @@ -896,6 +902,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, * connection, regardless of whether it's incoming or outgoing. * @param connectTimeMillis The connection time of the call. * @param clockProxy * @param featureFlags The telecom feature flags. */ Call( String callId, Loading @@ -914,11 +921,13 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, long connectTimeMillis, long connectElapsedTimeMillis, ClockProxy clockProxy, ToastFactory toastFactory) { ToastFactory toastFactory, FeatureFlags featureFlags) { this(callId, context, callsManager, lock, repository, phoneNumberUtilsAdapter, handle, gatewayInfo, connectionManagerPhoneAccountHandle, targetPhoneAccountHandle, callDirection, shouldAttachToExistingConnection, isConference, clockProxy, toastFactory); shouldAttachToExistingConnection, isConference, clockProxy, toastFactory, featureFlags); mConnectTimeMillis = connectTimeMillis; mConnectElapsedTimeMillis = connectElapsedTimeMillis; Loading Loading @@ -1770,8 +1779,12 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, 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()); UserHandle associatedUser = UserUtil.getAssociatedUserForCall( mFlags.workProfileAssociatedUser(), mCallsManager.getPhoneAccountRegistrar(), mCallsManager.getCurrentUserHandle(), accountHandle); if (isIncoming() && !associatedUser.equals(mAssociatedUser)) { setAssociatedUser(associatedUser); } } } Loading Loading @@ -4111,7 +4124,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, * @param associatedUser */ public void setAssociatedUser(UserHandle associatedUser) { Log.i(this, "Setting associated user for call"); Log.i(this, "Setting associated user for call: %s", associatedUser); Preconditions.checkNotNull(associatedUser); mAssociatedUser = associatedUser; } Loading src/com/android/server/telecom/CallsManager.java +42 −20 Original line number Diff line number Diff line Loading @@ -1482,7 +1482,8 @@ public class CallsManager extends Call.ListenerBase false /* forceAttachToExistingConnection */, isConference, /* isConference */ mClockProxy, mToastFactory); mToastFactory, mFeatureFlags); // 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 Loading @@ -1509,7 +1510,10 @@ public class CallsManager extends Call.ListenerBase } } // Incoming address was set via EXTRA_INCOMING_CALL_ADDRESS above. call.setAssociatedUser(phoneAccountHandle.getUserHandle()); UserHandle associatedUser = UserUtil.getAssociatedUserForCall( mFeatureFlags.workProfileAssociatedUser(), getPhoneAccountRegistrar(), getCurrentUserHandle(), phoneAccountHandle); call.setAssociatedUser(associatedUser); } if (phoneAccount != null) { Loading Loading @@ -1629,15 +1633,19 @@ public class CallsManager extends Call.ListenerBase // Check if the target phone account is possibly in ECBM. call.setIsInECBM(getEmergencyCallHelper() .isLastOutgoingEmergencyCallPAH(call.getTargetPhoneAccount())); // 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()) { // Check if call is visible to the current user. boolean isCallHiddenFromProfile = !isCallVisibleForUser(call, mCurrentUserHandle); // For admins, we should check if the work profile is paused in order to reject // the call. if (mUserManager.isUserAdmin(mCurrentUserHandle.getIdentifier())) { isCallHiddenFromProfile &= mUserManager.isQuietModeEnabled( call.getAssociatedUser()); } // We should always allow emergency calls and also allow non-emergency calls when ECBM // is active for the phone account. if (isCallHiddenFromProfile && !call.isEmergencyCall() && !call.isInECBM()) { Log.d(TAG, "Rejecting non-emergency call because the owner %s is not running.", phoneAccountHandle.getUserHandle()); call.setMissedReason(USER_MISSED_NOT_RUNNING); Loading Loading @@ -1710,11 +1718,15 @@ public class CallsManager extends Call.ListenerBase true /* forceAttachToExistingConnection */, false, /* isConference */ mClockProxy, mToastFactory); mToastFactory, mFeatureFlags); call.initAnalytics(); // For unknown calls, base the associated user off of the target phone account handle. call.setAssociatedUser(phoneAccountHandle.getUserHandle()); UserHandle associatedUser = UserUtil.getAssociatedUserForCall( mFeatureFlags.workProfileAssociatedUser(), getPhoneAccountRegistrar(), getCurrentUserHandle(), phoneAccountHandle); call.setAssociatedUser(associatedUser); setIntentExtrasAndStartTime(call, extras); call.addListener(this); notifyStartCreateConnection(call); Loading Loading @@ -1828,7 +1840,8 @@ public class CallsManager extends Call.ListenerBase false /* forceAttachToExistingConnection */, isConference, /* isConference */ mClockProxy, mToastFactory); mToastFactory, mFeatureFlags); if (extras.containsKey(TelecomManager.TRANSACTION_CALL_ID_KEY)) { call.setIsTransactionalCall(true); Loading Loading @@ -4235,7 +4248,8 @@ public class CallsManager extends Call.ListenerBase connectTime, connectElapsedTime, mClockProxy, mToastFactory); mToastFactory, mFeatureFlags); // Unlike connections, conferences are not created first and then notified as create // connection complete from the CS. They originate from the CS and are reported directly to Loading @@ -4253,7 +4267,10 @@ public class CallsManager extends Call.ListenerBase 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()); UserHandle associatedUser = UserUtil.getAssociatedUserForCall( mFeatureFlags.workProfileAssociatedUser(), getPhoneAccountRegistrar(), getCurrentUserHandle(), phoneAccount); call.setAssociatedUser(associatedUser); // 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(); Loading Loading @@ -5291,7 +5308,8 @@ public class CallsManager extends Call.ListenerBase connection.getConnectTimeMillis() /* connectTimeMillis */, connection.getConnectElapsedTimeMillis(), /* connectElapsedTimeMillis */ mClockProxy, mToastFactory); mToastFactory, mFeatureFlags); call.initAnalytics(); call.getAnalytics().setCreatedFromExistingConnection(true); Loading @@ -5306,7 +5324,10 @@ public class CallsManager extends Call.ListenerBase connection.getCallerDisplayNamePresentation()); // For existing connections, use the phone account user handle to determine the user // association with the call. call.setAssociatedUser(connection.getPhoneAccount().getUserHandle()); UserHandle associatedUser = UserUtil.getAssociatedUserForCall( mFeatureFlags.workProfileAssociatedUser(), getPhoneAccountRegistrar(), getCurrentUserHandle(), connection.getPhoneAccount()); call.setAssociatedUser(associatedUser); call.addListener(this); call.putConnectionServiceExtras(connection.getExtras()); Loading Loading @@ -5951,7 +5972,7 @@ public class CallsManager extends Call.ListenerBase handoverFromCall.getHandle(), null, null, null, Call.CALL_DIRECTION_OUTGOING, false, false, mClockProxy, mToastFactory); false, mClockProxy, mToastFactory, mFeatureFlags); call.initAnalytics(); // Set self-managed and voipAudioMode if destination is self-managed CS Loading Loading @@ -6158,7 +6179,8 @@ public class CallsManager extends Call.ListenerBase false /* forceAttachToExistingConnection */, false, /* isConference */ mClockProxy, mToastFactory); mToastFactory, mFeatureFlags); if (fromCall == null || isHandoverInProgress() || !isHandoverFromPhoneAccountSupported(fromCall.getTargetPhoneAccount()) || Loading src/com/android/server/telecom/InCallController.java +32 −8 Original line number Diff line number Diff line Loading @@ -82,6 +82,7 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; /** * Binds to {@link IInCallService} and provides the service to {@link CallsManager} through which it Loading Loading @@ -1406,17 +1407,31 @@ public class InCallController extends CallsManagerListenerBase implements @Override public void onCallRemoved(Call call) { Log.i(this, "onCallRemoved: %s", call); if (mCallsManager.getCalls().isEmpty()) { // Instead of checking if there are no active calls, we should check if there any calls with // the same associated user returned from getUserFromCall. For instance, it's possible to // have calls coexist on the personal profile and work profile, in which case, we would only // remove the ICS connection for the user associated with the call to be disconnected. UserHandle userFromCall = getUserFromCall(call); Stream<Call> callsAssociatedWithUserFromCall = mCallsManager.getCalls().stream() .filter((c) -> getUserFromCall(c).equals(userFromCall)); boolean isCallCountZero = mFeatureFlags.workProfileAssociatedUser() ? callsAssociatedWithUserFromCall.count() == 0 : mCallsManager.getCalls().isEmpty(); if (isCallCountZero) { /** Let's add a 2 second delay before we send unbind to the services to hopefully * give them enough time to process all the pending messages. */ mHandler.postDelayed(new Runnable("ICC.oCR", mLock) { @Override public void loggedRun() { // Check again to make sure there are no active calls. if (mCallsManager.getCalls().isEmpty()) { unbindFromServices(getUserFromCall(call)); // Check again to make sure there are no active calls for the associated user. Stream<Call> callsAssociatedWithUserFromCall = mCallsManager.getCalls().stream() .filter((c) -> getUserFromCall(c).equals(userFromCall)); boolean isCallCountZero = mFeatureFlags.workProfileAssociatedUser() ? callsAssociatedWithUserFromCall.count() == 0 : mCallsManager.getCalls().isEmpty(); if (isCallCountZero) { unbindFromServices(userFromCall); mEmergencyCallHelper.maybeRevokeTemporaryLocationPermission(); } } Loading Loading @@ -1832,6 +1847,7 @@ public class InCallController extends CallsManagerListenerBase implements * Unbinds an existing bound connection to the in-call app. */ public void unbindFromServices(UserHandle userHandle) { Log.i(this, "Unbinding from services for user %s", userHandle); try { mContext.unregisterReceiver(mPackageChangedReceiver); } catch (IllegalArgumentException e) { Loading Loading @@ -2320,7 +2336,9 @@ public class InCallController extends CallsManagerListenerBase implements } // Upon successful connection, send the state of the world to the service. List<Call> calls = orderCallsWithChildrenFirst(mCallsManager.getCalls()); List<Call> calls = orderCallsWithChildrenFirst(mCallsManager.getCalls().stream().filter( call -> getUserFromCall(call).equals(userHandle)) .collect(Collectors.toUnmodifiableList())); Log.i(this, "Adding %s calls to InCallService after onConnected: %s, including external " + "calls", calls.size(), info.getComponentName()); int numCallsSent = 0; Loading Loading @@ -2463,6 +2481,9 @@ public class InCallController extends CallsManagerListenerBase implements } } Log.i(this, "Components updated: %s", componentsUpdated); } else { Log.i(this, "Unable to update call. InCallService not found for user: %s", userFromCall); } } Loading Loading @@ -2901,8 +2922,11 @@ public class InCallController extends CallsManagerListenerBase implements } else { 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. // Emergency call should never be blocked, so if the user associated with the target // phone account handle user is in quiet mode, use the current user for the ecall. // Note, that this only applies to incoming calls that are received on assigned // sims (i.e. work sim), where the associated user would be the target phone account // handle user. if ((call.isEmergencyCall() || call.isInECBM()) && (userManager.isQuietModeEnabled(userFromCall) // We should also account for secondary/guest users where the profile may not Loading Loading
flags/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ aconfig_declarations { "telecom_calllog_flags.aconfig", "telecom_resolve_hidden_dependencies.aconfig", "telecom_bluetoothroutemanager_flags.aconfig", "telecom_work_profile_flags.aconfig" ], }
flags/telecom_work_profile_flags.aconfig 0 → 100644 +8 −0 Original line number Diff line number Diff line package: "com.android.server.telecom.flags" flag { name: "work_profile_associated_user" namespace: "telecom" description: "Redefines the associated user for calls in the context of work profile support (U+)" bug: "294699269" } No newline at end of file
src/com/android/server/telecom/Call.java +21 −8 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ import android.widget.Toast; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telecom.IVideoProvider; import com.android.internal.util.Preconditions; import com.android.server.telecom.flags.FeatureFlags; import com.android.server.telecom.stats.CallFailureCause; import com.android.server.telecom.stats.CallStateChangedAtomWriter; import com.android.server.telecom.ui.ToastFactory; Loading Loading @@ -788,6 +789,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, */ private CompletableFuture<Boolean> mDisconnectFuture; private FeatureFlags mFlags; /** * Persists the specified parameters and initializes the new instance. * @param context The context. Loading Loading @@ -819,11 +822,12 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, boolean shouldAttachToExistingConnection, boolean isConference, ClockProxy clockProxy, ToastFactory toastFactory) { ToastFactory toastFactory, FeatureFlags featureFlags) { this(callId, context, callsManager, lock, repository, phoneNumberUtilsAdapter, handle, null, gatewayInfo, connectionManagerPhoneAccountHandle, targetPhoneAccountHandle, callDirection, shouldAttachToExistingConnection, isConference, clockProxy, toastFactory); isConference, clockProxy, toastFactory, featureFlags); } Loading @@ -843,8 +847,10 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, boolean shouldAttachToExistingConnection, boolean isConference, ClockProxy clockProxy, ToastFactory toastFactory) { ToastFactory toastFactory, FeatureFlags featureFlags) { mFlags = featureFlags; mId = callId; mConnectionId = callId; mState = (isConference && callDirection != CALL_DIRECTION_INCOMING && Loading Loading @@ -896,6 +902,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, * connection, regardless of whether it's incoming or outgoing. * @param connectTimeMillis The connection time of the call. * @param clockProxy * @param featureFlags The telecom feature flags. */ Call( String callId, Loading @@ -914,11 +921,13 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, long connectTimeMillis, long connectElapsedTimeMillis, ClockProxy clockProxy, ToastFactory toastFactory) { ToastFactory toastFactory, FeatureFlags featureFlags) { this(callId, context, callsManager, lock, repository, phoneNumberUtilsAdapter, handle, gatewayInfo, connectionManagerPhoneAccountHandle, targetPhoneAccountHandle, callDirection, shouldAttachToExistingConnection, isConference, clockProxy, toastFactory); shouldAttachToExistingConnection, isConference, clockProxy, toastFactory, featureFlags); mConnectTimeMillis = connectTimeMillis; mConnectElapsedTimeMillis = connectElapsedTimeMillis; Loading Loading @@ -1770,8 +1779,12 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, 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()); UserHandle associatedUser = UserUtil.getAssociatedUserForCall( mFlags.workProfileAssociatedUser(), mCallsManager.getPhoneAccountRegistrar(), mCallsManager.getCurrentUserHandle(), accountHandle); if (isIncoming() && !associatedUser.equals(mAssociatedUser)) { setAssociatedUser(associatedUser); } } } Loading Loading @@ -4111,7 +4124,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, * @param associatedUser */ public void setAssociatedUser(UserHandle associatedUser) { Log.i(this, "Setting associated user for call"); Log.i(this, "Setting associated user for call: %s", associatedUser); Preconditions.checkNotNull(associatedUser); mAssociatedUser = associatedUser; } Loading
src/com/android/server/telecom/CallsManager.java +42 −20 Original line number Diff line number Diff line Loading @@ -1482,7 +1482,8 @@ public class CallsManager extends Call.ListenerBase false /* forceAttachToExistingConnection */, isConference, /* isConference */ mClockProxy, mToastFactory); mToastFactory, mFeatureFlags); // 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 Loading @@ -1509,7 +1510,10 @@ public class CallsManager extends Call.ListenerBase } } // Incoming address was set via EXTRA_INCOMING_CALL_ADDRESS above. call.setAssociatedUser(phoneAccountHandle.getUserHandle()); UserHandle associatedUser = UserUtil.getAssociatedUserForCall( mFeatureFlags.workProfileAssociatedUser(), getPhoneAccountRegistrar(), getCurrentUserHandle(), phoneAccountHandle); call.setAssociatedUser(associatedUser); } if (phoneAccount != null) { Loading Loading @@ -1629,15 +1633,19 @@ public class CallsManager extends Call.ListenerBase // Check if the target phone account is possibly in ECBM. call.setIsInECBM(getEmergencyCallHelper() .isLastOutgoingEmergencyCallPAH(call.getTargetPhoneAccount())); // 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()) { // Check if call is visible to the current user. boolean isCallHiddenFromProfile = !isCallVisibleForUser(call, mCurrentUserHandle); // For admins, we should check if the work profile is paused in order to reject // the call. if (mUserManager.isUserAdmin(mCurrentUserHandle.getIdentifier())) { isCallHiddenFromProfile &= mUserManager.isQuietModeEnabled( call.getAssociatedUser()); } // We should always allow emergency calls and also allow non-emergency calls when ECBM // is active for the phone account. if (isCallHiddenFromProfile && !call.isEmergencyCall() && !call.isInECBM()) { Log.d(TAG, "Rejecting non-emergency call because the owner %s is not running.", phoneAccountHandle.getUserHandle()); call.setMissedReason(USER_MISSED_NOT_RUNNING); Loading Loading @@ -1710,11 +1718,15 @@ public class CallsManager extends Call.ListenerBase true /* forceAttachToExistingConnection */, false, /* isConference */ mClockProxy, mToastFactory); mToastFactory, mFeatureFlags); call.initAnalytics(); // For unknown calls, base the associated user off of the target phone account handle. call.setAssociatedUser(phoneAccountHandle.getUserHandle()); UserHandle associatedUser = UserUtil.getAssociatedUserForCall( mFeatureFlags.workProfileAssociatedUser(), getPhoneAccountRegistrar(), getCurrentUserHandle(), phoneAccountHandle); call.setAssociatedUser(associatedUser); setIntentExtrasAndStartTime(call, extras); call.addListener(this); notifyStartCreateConnection(call); Loading Loading @@ -1828,7 +1840,8 @@ public class CallsManager extends Call.ListenerBase false /* forceAttachToExistingConnection */, isConference, /* isConference */ mClockProxy, mToastFactory); mToastFactory, mFeatureFlags); if (extras.containsKey(TelecomManager.TRANSACTION_CALL_ID_KEY)) { call.setIsTransactionalCall(true); Loading Loading @@ -4235,7 +4248,8 @@ public class CallsManager extends Call.ListenerBase connectTime, connectElapsedTime, mClockProxy, mToastFactory); mToastFactory, mFeatureFlags); // Unlike connections, conferences are not created first and then notified as create // connection complete from the CS. They originate from the CS and are reported directly to Loading @@ -4253,7 +4267,10 @@ public class CallsManager extends Call.ListenerBase 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()); UserHandle associatedUser = UserUtil.getAssociatedUserForCall( mFeatureFlags.workProfileAssociatedUser(), getPhoneAccountRegistrar(), getCurrentUserHandle(), phoneAccount); call.setAssociatedUser(associatedUser); // 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(); Loading Loading @@ -5291,7 +5308,8 @@ public class CallsManager extends Call.ListenerBase connection.getConnectTimeMillis() /* connectTimeMillis */, connection.getConnectElapsedTimeMillis(), /* connectElapsedTimeMillis */ mClockProxy, mToastFactory); mToastFactory, mFeatureFlags); call.initAnalytics(); call.getAnalytics().setCreatedFromExistingConnection(true); Loading @@ -5306,7 +5324,10 @@ public class CallsManager extends Call.ListenerBase connection.getCallerDisplayNamePresentation()); // For existing connections, use the phone account user handle to determine the user // association with the call. call.setAssociatedUser(connection.getPhoneAccount().getUserHandle()); UserHandle associatedUser = UserUtil.getAssociatedUserForCall( mFeatureFlags.workProfileAssociatedUser(), getPhoneAccountRegistrar(), getCurrentUserHandle(), connection.getPhoneAccount()); call.setAssociatedUser(associatedUser); call.addListener(this); call.putConnectionServiceExtras(connection.getExtras()); Loading Loading @@ -5951,7 +5972,7 @@ public class CallsManager extends Call.ListenerBase handoverFromCall.getHandle(), null, null, null, Call.CALL_DIRECTION_OUTGOING, false, false, mClockProxy, mToastFactory); false, mClockProxy, mToastFactory, mFeatureFlags); call.initAnalytics(); // Set self-managed and voipAudioMode if destination is self-managed CS Loading Loading @@ -6158,7 +6179,8 @@ public class CallsManager extends Call.ListenerBase false /* forceAttachToExistingConnection */, false, /* isConference */ mClockProxy, mToastFactory); mToastFactory, mFeatureFlags); if (fromCall == null || isHandoverInProgress() || !isHandoverFromPhoneAccountSupported(fromCall.getTargetPhoneAccount()) || Loading
src/com/android/server/telecom/InCallController.java +32 −8 Original line number Diff line number Diff line Loading @@ -82,6 +82,7 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; /** * Binds to {@link IInCallService} and provides the service to {@link CallsManager} through which it Loading Loading @@ -1406,17 +1407,31 @@ public class InCallController extends CallsManagerListenerBase implements @Override public void onCallRemoved(Call call) { Log.i(this, "onCallRemoved: %s", call); if (mCallsManager.getCalls().isEmpty()) { // Instead of checking if there are no active calls, we should check if there any calls with // the same associated user returned from getUserFromCall. For instance, it's possible to // have calls coexist on the personal profile and work profile, in which case, we would only // remove the ICS connection for the user associated with the call to be disconnected. UserHandle userFromCall = getUserFromCall(call); Stream<Call> callsAssociatedWithUserFromCall = mCallsManager.getCalls().stream() .filter((c) -> getUserFromCall(c).equals(userFromCall)); boolean isCallCountZero = mFeatureFlags.workProfileAssociatedUser() ? callsAssociatedWithUserFromCall.count() == 0 : mCallsManager.getCalls().isEmpty(); if (isCallCountZero) { /** Let's add a 2 second delay before we send unbind to the services to hopefully * give them enough time to process all the pending messages. */ mHandler.postDelayed(new Runnable("ICC.oCR", mLock) { @Override public void loggedRun() { // Check again to make sure there are no active calls. if (mCallsManager.getCalls().isEmpty()) { unbindFromServices(getUserFromCall(call)); // Check again to make sure there are no active calls for the associated user. Stream<Call> callsAssociatedWithUserFromCall = mCallsManager.getCalls().stream() .filter((c) -> getUserFromCall(c).equals(userFromCall)); boolean isCallCountZero = mFeatureFlags.workProfileAssociatedUser() ? callsAssociatedWithUserFromCall.count() == 0 : mCallsManager.getCalls().isEmpty(); if (isCallCountZero) { unbindFromServices(userFromCall); mEmergencyCallHelper.maybeRevokeTemporaryLocationPermission(); } } Loading Loading @@ -1832,6 +1847,7 @@ public class InCallController extends CallsManagerListenerBase implements * Unbinds an existing bound connection to the in-call app. */ public void unbindFromServices(UserHandle userHandle) { Log.i(this, "Unbinding from services for user %s", userHandle); try { mContext.unregisterReceiver(mPackageChangedReceiver); } catch (IllegalArgumentException e) { Loading Loading @@ -2320,7 +2336,9 @@ public class InCallController extends CallsManagerListenerBase implements } // Upon successful connection, send the state of the world to the service. List<Call> calls = orderCallsWithChildrenFirst(mCallsManager.getCalls()); List<Call> calls = orderCallsWithChildrenFirst(mCallsManager.getCalls().stream().filter( call -> getUserFromCall(call).equals(userHandle)) .collect(Collectors.toUnmodifiableList())); Log.i(this, "Adding %s calls to InCallService after onConnected: %s, including external " + "calls", calls.size(), info.getComponentName()); int numCallsSent = 0; Loading Loading @@ -2463,6 +2481,9 @@ public class InCallController extends CallsManagerListenerBase implements } } Log.i(this, "Components updated: %s", componentsUpdated); } else { Log.i(this, "Unable to update call. InCallService not found for user: %s", userFromCall); } } Loading Loading @@ -2901,8 +2922,11 @@ public class InCallController extends CallsManagerListenerBase implements } else { 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. // Emergency call should never be blocked, so if the user associated with the target // phone account handle user is in quiet mode, use the current user for the ecall. // Note, that this only applies to incoming calls that are received on assigned // sims (i.e. work sim), where the associated user would be the target phone account // handle user. if ((call.isEmergencyCall() || call.isInECBM()) && (userManager.isQuietModeEnabled(userFromCall) // We should also account for secondary/guest users where the profile may not Loading