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

Commit 29b71071 authored by Pranav Madapurmath's avatar Pranav Madapurmath
Browse files

Enforce outgoing conference call restriction.

When the user has the UserManager.DISALLOW_OUTGOING_CALLS restriction
set, it is still possible for an app to start a conference via
TM#startConference. Unlike TM#placeCall, which hits
UserCallIntentProcessor, TM#startConference calls into CallsManager
directly, bypassing the outgoing call restriction check.

We should ensure that the outgoing call restriction gets applied when an
app invokes TM#startConference. I verified locally from
AdhocConferenceTest that the conference calls are placed even when the
outgoing call restriction is set.

Bug: 290920435
Test: atest AdhocConferenceTest (set up device with outgoing call
restriction on admin and verified that associated tests fail when
TM#startConference is invoked)

Change-Id: I0f3d5396bd8cf831a441567fbdad578a9166a838
parent c6c64f11
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@ import com.android.server.telecom.callfiltering.IncomingCallFilterGraph;
import com.android.server.telecom.callredirection.CallRedirectionProcessor;
import com.android.server.telecom.components.ErrorDialogActivity;
import com.android.server.telecom.components.TelecomBroadcastReceiver;
import com.android.server.telecom.components.UserCallIntentProcessor;
import com.android.server.telecom.flags.FeatureFlags;
import com.android.server.telecom.stats.CallFailureCause;
import com.android.server.telecom.ui.AudioProcessingNotification;
@@ -2313,6 +2314,15 @@ public class CallsManager extends Call.ListenerBase

         PhoneAccountHandle phoneAccountHandle = clientExtras.getParcelable(
                 TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
         PhoneAccount account =
                mPhoneAccountRegistrar.getPhoneAccount(phoneAccountHandle, initiatingUser);
         boolean isSelfManaged = account != null && account.isSelfManaged();
         // Enforce outgoing call restriction for conference calls. This is handled via
         // UserCallIntentProcessor for normal MO calls.
         if (UserUtil.hasOutgoingCallsUserRestriction(mContext, initiatingUser,
                 null, isSelfManaged, CallsManager.class.getCanonicalName())) {
             return;
         }
         CompletableFuture<Call> callFuture = startOutgoingCall(participants, phoneAccountHandle,
                 clientExtras, initiatingUser, null/* originalIntent */, callingPackage,
                 true/* isconference*/);
+59 −0
Original line number Diff line number Diff line
@@ -16,10 +16,16 @@

package com.android.server.telecom;

import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.net.Uri;
import android.os.UserHandle;
import android.os.UserManager;
import android.telecom.Log;

import com.android.server.telecom.components.ErrorDialogActivity;

public final class UserUtil {

@@ -40,4 +46,57 @@ public final class UserUtil {
        UserInfo userInfo = getUserInfoFromUserHandle(context, userHandle);
        return userInfo != null && userInfo.profileGroupId != userInfo.id;
    }

    public static void showErrorDialogForRestrictedOutgoingCall(Context context,
            int stringId, String tag, String reason) {
        final Intent intent = new Intent(context, ErrorDialogActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra(ErrorDialogActivity.ERROR_MESSAGE_ID_EXTRA, stringId);
        context.startActivityAsUser(intent, UserHandle.CURRENT);
        Log.w(tag, "Rejecting non-emergency phone call because "
                + reason);
    }

    public static boolean hasOutgoingCallsUserRestriction(Context context,
            UserHandle userHandle, Uri handle, boolean isSelfManaged, String tag) {
        // Set handle for conference calls. Refer to {@link Connection#ADHOC_CONFERENCE_ADDRESS}.
        if (handle == null) {
            handle = Uri.parse("tel:conf-factory");
        }

        if(!isSelfManaged) {
            // Check DISALLOW_OUTGOING_CALLS restriction. Note: We are skipping this
            // check in a managed profile user because this check can always be bypassed
            // by copying and pasting the phone number into the personal dialer.
            if (!UserUtil.isManagedProfile(context, userHandle)) {
                // Only emergency calls are allowed for users with the DISALLOW_OUTGOING_CALLS
                // restriction.
                if (!TelephonyUtil.shouldProcessAsEmergency(context, handle)) {
                    final UserManager userManager =
                            (UserManager) context.getSystemService(Context.USER_SERVICE);
                    if (userManager.hasBaseUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
                            userHandle)) {
                        String reason = "of DISALLOW_OUTGOING_CALLS restriction";
                        showErrorDialogForRestrictedOutgoingCall(context,
                                R.string.outgoing_call_not_allowed_user_restriction, tag, reason);
                        return true;
                    } else if (userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
                            userHandle)) {
                        final DevicePolicyManager dpm =
                                context.getSystemService(DevicePolicyManager.class);
                        if (dpm == null) {
                            return true;
                        }
                        final Intent adminSupportIntent = dpm.createAdminSupportIntent(
                                UserManager.DISALLOW_OUTGOING_CALLS);
                        if (adminSupportIntent != null) {
                            context.startActivity(adminSupportIntent);
                        }
                        return true;
                    }
                }
            }
        }
        return false;
    }
}
+8 −45
Original line number Diff line number Diff line
@@ -105,47 +105,17 @@ public class UserCallIntentProcessor {
            handle = Uri.fromParts(PhoneAccount.SCHEME_SIP, uriString, null);
        }

       if(!isSelfManaged) {
            // Check DISALLOW_OUTGOING_CALLS restriction. Note: We are skipping this
            // check in a managed profile user because this check can always be bypassed
            // by copying and pasting the phone number into the personal dialer.
            if (!UserUtil.isManagedProfile(mContext, mUserHandle)) {
                // Only emergency calls are allowed for users with the DISALLOW_OUTGOING_CALLS
                // restriction.
                if (!TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) {
                    final UserManager userManager =
                            (UserManager) mContext.getSystemService(Context.USER_SERVICE);
                    if (userManager.hasBaseUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
                            mUserHandle)) {
                        showErrorDialogForRestrictedOutgoingCall(mContext,
                                R.string.outgoing_call_not_allowed_user_restriction);
                        Log.w(this, "Rejecting non-emergency phone call "
                                + "due to DISALLOW_OUTGOING_CALLS restriction");
       if (UserUtil.hasOutgoingCallsUserRestriction(mContext, mUserHandle,
               handle, isSelfManaged, UserCallIntentProcessor.class.getCanonicalName())) {
           return;
                    } else if (userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
                            mUserHandle)) {
                        final DevicePolicyManager dpm =
                                mContext.getSystemService(DevicePolicyManager.class);
                        if (dpm == null) {
                            return;
                        }
                        final Intent adminSupportIntent = dpm.createAdminSupportIntent(
                                UserManager.DISALLOW_OUTGOING_CALLS);
                        if (adminSupportIntent != null) {
                            mContext.startActivity(adminSupportIntent);
                        }
                        return;
                    }
                }
            }
       }

        if (!isSelfManaged && !canCallNonEmergency &&
                !TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) {
            showErrorDialogForRestrictedOutgoingCall(mContext,
                    R.string.outgoing_call_not_allowed_no_permission);
            Log.w(this, "Rejecting non-emergency phone call because "
                    + android.Manifest.permission.CALL_PHONE + " permission is not granted.");
            String reason = android.Manifest.permission.CALL_PHONE + " permission is not granted.";
            UserUtil.showErrorDialogForRestrictedOutgoingCall(mContext,
                    R.string.outgoing_call_not_allowed_no_permission,
                    this.getClass().getCanonicalName(), reason);
            return;
        }

@@ -187,11 +157,4 @@ public class UserCallIntentProcessor {
        }
        return true;
    }

    private static void showErrorDialogForRestrictedOutgoingCall(Context context, int stringId) {
        final Intent intent = new Intent(context, ErrorDialogActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra(ErrorDialogActivity.ERROR_MESSAGE_ID_EXTRA, stringId);
        context.startActivityAsUser(intent, UserHandle.CURRENT);
    }
}