1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.telecom.components;
18 
19 import android.app.admin.DevicePolicyManager;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.net.Uri;
23 import android.os.UserHandle;
24 import android.os.UserManager;
25 import android.telecom.Log;
26 import android.telecom.PhoneAccount;
27 import android.telecom.TelecomManager;
28 import android.telecom.VideoProfile;
29 import android.telephony.PhoneNumberUtils;
30 import android.telephony.TelephonyManager;
31 
32 import com.android.server.telecom.CallIntentProcessor;
33 import com.android.server.telecom.R;
34 import com.android.server.telecom.TelecomSystem;
35 import com.android.server.telecom.TelephonyUtil;
36 import com.android.server.telecom.UserUtil;
37 import com.android.server.telecom.flags.FeatureFlags;
38 
39 // TODO: Needed for move to system service: import com.android.internal.R;
40 
41 /**
42  * Handles system CALL actions and forwards them to {@link CallIntentProcessor}.
43  * Handles all three CALL action types: CALL, CALL_PRIVILEGED, and CALL_EMERGENCY.
44  *
45  * Pre-L, the only way apps were were allowed to make outgoing emergency calls was the
46  * ACTION_CALL_PRIVILEGED action (which requires the system only CALL_PRIVILEGED permission).
47  *
48  * In L, any app that has the CALL_PRIVILEGED permission can continue to make outgoing emergency
49  * calls via ACTION_CALL_PRIVILEGED.
50  *
51  * In addition, the default dialer (identified via
52  * {@link android.telecom.TelecomManager#getDefaultDialerPackage()} will also be granted the
53  * ability to make emergency outgoing calls using the CALL action. In order to do this, it must
54  * use the {@link TelecomManager#placeCall(Uri, android.os.Bundle)} method to allow its package
55  * name to be passed to {@link UserCallIntentProcessor}. Calling startActivity will continue to
56  * work on all non-emergency numbers just like it did pre-L.
57  */
58 public class UserCallIntentProcessor {
59 
60     private final Context mContext;
61     private final UserHandle mUserHandle;
62     private FeatureFlags mFeatureFlags;
63 
UserCallIntentProcessor(Context context, UserHandle userHandle, FeatureFlags featureFlags)64     public UserCallIntentProcessor(Context context, UserHandle userHandle,
65             FeatureFlags featureFlags) {
66         mContext = context;
67         mUserHandle = userHandle;
68         mFeatureFlags = featureFlags;
69     }
70 
71     /**
72      * Processes intents sent to the activity.
73      *
74      * @param intent The intent.
75      * @param callingPackageName The package name of the calling app.
76      * @param isSelfManaged      {@code true} if SelfManaged profile enabled.
77      * @param canCallNonEmergency {@code true} if the caller is permitted to call non-emergency
78      *                            numbers.
79      * @param isLocalInvocation {@code true} if the caller is within the system service (i.e. the
80      *                            caller is {@link com.android.server.telecom.TelecomServiceImpl})
81      *                            and we can skip the re-broadcast of the intent to Telecom.
82      *                            When {@code false}, we need to re-broadcast the intent to Telcom
83      *                            to trampoline it to the system service where the Telecom
84      *                            service resides.
85      */
processIntent(Intent intent, String callingPackageName, boolean isSelfManaged, boolean canCallNonEmergency, boolean isLocalInvocation)86     public void processIntent(Intent intent, String callingPackageName,
87             boolean isSelfManaged, boolean canCallNonEmergency,
88             boolean isLocalInvocation) {
89         String action = intent.getAction();
90 
91         if (Intent.ACTION_CALL.equals(action) ||
92                 Intent.ACTION_CALL_PRIVILEGED.equals(action) ||
93                 Intent.ACTION_CALL_EMERGENCY.equals(action)) {
94             processOutgoingCallIntent(intent, callingPackageName, isSelfManaged,
95                     canCallNonEmergency, isLocalInvocation);
96         }
97     }
98 
processOutgoingCallIntent(Intent intent, String callingPackageName, boolean isSelfManaged, boolean canCallNonEmergency, boolean isLocalInvocation)99     private void processOutgoingCallIntent(Intent intent, String callingPackageName,
100             boolean isSelfManaged, boolean canCallNonEmergency,
101             boolean isLocalInvocation) {
102         Uri handle = intent.getData();
103         if (handle == null) return;
104         String scheme = handle.getScheme();
105         String uriString = handle.getSchemeSpecificPart();
106 
107         // Ensure sip URIs dialed using TEL scheme get converted to SIP scheme.
108         if (PhoneAccount.SCHEME_TEL.equals(scheme) && PhoneNumberUtils.isUriNumber(uriString)) {
109             handle = Uri.fromParts(PhoneAccount.SCHEME_SIP, uriString, null);
110         }
111 
112        if (UserUtil.hasOutgoingCallsUserRestriction(mContext, mUserHandle, handle, isSelfManaged,
113                UserCallIntentProcessor.class.getCanonicalName(), mFeatureFlags)) {
114            return;
115        }
116 
117         if (!isSelfManaged && !canCallNonEmergency &&
118                 !TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) {
119             String reason = android.Manifest.permission.CALL_PHONE + " permission is not granted.";
120             UserUtil.showErrorDialogForRestrictedOutgoingCall(mContext,
121                     R.string.outgoing_call_not_allowed_no_permission,
122                     this.getClass().getCanonicalName(), reason);
123             return;
124         }
125 
126         int videoState = intent.getIntExtra(
127                 TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
128                 VideoProfile.STATE_AUDIO_ONLY);
129         Log.d(this, "processOutgoingCallIntent videoState = " + videoState);
130 
131         // Save the user handle of current user before forwarding the intent to primary user.
132         intent.putExtra(CallIntentProcessor.KEY_INITIATING_USER, mUserHandle);
133 
134         sendIntentToDestination(intent, isLocalInvocation, callingPackageName);
135     }
136 
137     /**
138      * Potentially trampolines the intent to Telecom via TelecomServiceImpl.
139      * If the caller is local to the Telecom service, we send the intent to Telecom without
140      * sending it through TelecomServiceImpl.
141      */
sendIntentToDestination(Intent intent, boolean isLocalInvocation, String callingPackage)142     private boolean sendIntentToDestination(Intent intent, boolean isLocalInvocation,
143             String callingPackage) {
144         intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, false);
145         intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
146         if (isLocalInvocation) {
147             // We are invoking this from TelecomServiceImpl, so TelecomSystem is available.  Don't
148             // bother trampolining the intent, just sent it directly to the call intent processor.
149             // TODO: We should not be using an intent here; this whole flows needs cleanup.
150             Log.i(this, "sendIntentToDestination: send intent to Telecom directly.");
151             synchronized (TelecomSystem.getInstance().getLock()) {
152                 TelecomSystem.getInstance().getCallIntentProcessor().processIntent(intent,
153                         callingPackage);
154             }
155         } else {
156             // We're calling from the UserCallActivity, so the TelecomSystem is not in the same
157             // process; we need to trampoline to TelecomSystem in the system server process.
158             Log.i(this, "sendIntentToDestination: trampoline to Telecom.");
159             TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
160             tm.handleCallIntent(intent, callingPackage);
161         }
162         return true;
163     }
164 }
165