Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 26b9fdc5 authored by Pranav Madapurmath's avatar Pranav Madapurmath Committed by Android (Google) Code Review
Browse files

Merge "Associate calls with profile user." into main

parents 1d71b0a4 a328efad
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ aconfig_declarations {
      "telecom_calllog_flags.aconfig",
      "telecom_resolve_hidden_dependencies.aconfig",
      "telecom_bluetoothroutemanager_flags.aconfig",
      "telecom_work_profile_flags.aconfig"
    ],
}
+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
+21 −8
Original line number Diff line number Diff line
@@ -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;
@@ -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.
@@ -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);

    }

@@ -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 &&
@@ -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,
@@ -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;
@@ -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);
            }
        }
    }
@@ -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;
    }
+42 −20
Original line number Diff line number Diff line
@@ -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
@@ -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) {
@@ -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);
@@ -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);
@@ -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);
@@ -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
@@ -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();
@@ -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);
@@ -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());

@@ -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
@@ -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()) ||
+32 −8
Original line number Diff line number Diff line
@@ -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
@@ -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();
                    }
                }
@@ -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) {
@@ -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;
@@ -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);
        }
    }

@@ -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