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
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index bc0fe49..c719c77 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -132,6 +132,7 @@
 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 @@
 
          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*/);
diff --git a/src/com/android/server/telecom/UserUtil.java b/src/com/android/server/telecom/UserUtil.java
index a304401..507763c 100644
--- a/src/com/android/server/telecom/UserUtil.java
+++ b/src/com/android/server/telecom/UserUtil.java
@@ -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 @@
         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;
+    }
 }
diff --git a/src/com/android/server/telecom/components/UserCallIntentProcessor.java b/src/com/android/server/telecom/components/UserCallIntentProcessor.java
index a4602c1..41232c2 100755
--- a/src/com/android/server/telecom/components/UserCallIntentProcessor.java
+++ b/src/com/android/server/telecom/components/UserCallIntentProcessor.java
@@ -105,47 +105,17 @@
             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");
-                        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 (UserUtil.hasOutgoingCallsUserRestriction(mContext, mUserHandle,
+               handle, isSelfManaged, UserCallIntentProcessor.class.getCanonicalName())) {
+           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 @@
         }
         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);
-    }
 }