• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 com.android.server.telecom.CallIntentProcessor;
20 import com.android.server.telecom.R;
21 import com.android.server.telecom.TelephonyUtil;
22 import com.android.server.telecom.UserUtil;
23 import com.android.settingslib.RestrictedLockUtils;
24 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
25 
26 import android.app.AppOpsManager;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.pm.PackageManager;
30 import android.net.Uri;
31 import android.os.UserHandle;
32 import android.os.UserManager;
33 import android.telecom.DefaultDialerManager;
34 import android.telecom.Log;
35 import android.telecom.PhoneAccount;
36 import android.telecom.TelecomManager;
37 import android.telecom.VideoProfile;
38 import android.telephony.PhoneNumberUtils;
39 import android.text.TextUtils;
40 import android.widget.Toast;
41 
42 // TODO: Needed for move to system service: import com.android.internal.R;
43 
44 /**
45  * Handles system CALL actions and forwards them to {@link CallIntentProcessor}.
46  * Handles all three CALL action types: CALL, CALL_PRIVILEGED, and CALL_EMERGENCY.
47  *
48  * Pre-L, the only way apps were were allowed to make outgoing emergency calls was the
49  * ACTION_CALL_PRIVILEGED action (which requires the system only CALL_PRIVILEGED permission).
50  *
51  * In L, any app that has the CALL_PRIVILEGED permission can continue to make outgoing emergency
52  * calls via ACTION_CALL_PRIVILEGED.
53  *
54  * In addition, the default dialer (identified via
55  * {@link android.telecom.TelecomManager#getDefaultDialerPackage()} will also be granted the
56  * ability to make emergency outgoing calls using the CALL action. In order to do this, it must
57  * use the {@link TelecomManager#placeCall(Uri, android.os.Bundle)} method to allow its package
58  * name to be passed to {@link UserCallIntentProcessor}. Calling startActivity will continue to
59  * work on all non-emergency numbers just like it did pre-L.
60  */
61 public class UserCallIntentProcessor {
62 
63     private final Context mContext;
64     private final UserHandle mUserHandle;
65 
UserCallIntentProcessor(Context context, UserHandle userHandle)66     public UserCallIntentProcessor(Context context, UserHandle userHandle) {
67         mContext = context;
68         mUserHandle = userHandle;
69     }
70 
71     /**
72      * Processes intents sent to the activity.
73      *
74      * @param intent The intent.
75      */
processIntent(Intent intent, String callingPackageName, boolean canCallNonEmergency)76     public void processIntent(Intent intent, String callingPackageName,
77             boolean canCallNonEmergency) {
78         // Ensure call intents are not processed on devices that are not capable of calling.
79         if (!isVoiceCapable()) {
80             return;
81         }
82 
83         String action = intent.getAction();
84 
85         if (Intent.ACTION_CALL.equals(action) ||
86                 Intent.ACTION_CALL_PRIVILEGED.equals(action) ||
87                 Intent.ACTION_CALL_EMERGENCY.equals(action)) {
88             processOutgoingCallIntent(intent, callingPackageName, canCallNonEmergency);
89         }
90     }
91 
processOutgoingCallIntent(Intent intent, String callingPackageName, boolean canCallNonEmergency)92     private void processOutgoingCallIntent(Intent intent, String callingPackageName,
93             boolean canCallNonEmergency) {
94         Uri handle = intent.getData();
95         String scheme = handle.getScheme();
96         String uriString = handle.getSchemeSpecificPart();
97 
98         if (!PhoneAccount.SCHEME_VOICEMAIL.equals(scheme)) {
99             handle = Uri.fromParts(PhoneNumberUtils.isUriNumber(uriString) ?
100                     PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL, uriString, null);
101         }
102 
103         // Check DISALLOW_OUTGOING_CALLS restriction. Note: We are skipping this check in a managed
104         // profile user because this check can always be bypassed by copying and pasting the phone
105         // number into the personal dialer.
106         if (!UserUtil.isManagedProfile(mContext, mUserHandle)) {
107             // Only emergency calls are allowed for users with the DISALLOW_OUTGOING_CALLS
108             // restriction.
109             if (!TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) {
110                 final UserManager userManager = (UserManager) mContext.getSystemService(
111                         Context.USER_SERVICE);
112                 if (userManager.hasBaseUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
113                         mUserHandle)) {
114                     showErrorDialogForRestrictedOutgoingCall(mContext,
115                             R.string.outgoing_call_not_allowed_user_restriction);
116                     Log.w(this, "Rejecting non-emergency phone call due to DISALLOW_OUTGOING_CALLS "
117                             + "restriction");
118                     return;
119                 } else if (userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
120                         mUserHandle)) {
121                     RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext,
122                             EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN);
123                     return;
124                 }
125             }
126         }
127 
128         if (!canCallNonEmergency && !TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) {
129             showErrorDialogForRestrictedOutgoingCall(mContext,
130                     R.string.outgoing_call_not_allowed_no_permission);
131             Log.w(this, "Rejecting non-emergency phone call because "
132                     + android.Manifest.permission.CALL_PHONE + " permission is not granted.");
133             return;
134         }
135 
136         int videoState = intent.getIntExtra(
137                 TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
138                 VideoProfile.STATE_AUDIO_ONLY);
139         Log.d(this, "processOutgoingCallIntent videoState = " + videoState);
140 
141         intent.putExtra(CallIntentProcessor.KEY_IS_PRIVILEGED_DIALER,
142                 isDefaultOrSystemDialer(callingPackageName));
143 
144         // Save the user handle of current user before forwarding the intent to primary user.
145         intent.putExtra(CallIntentProcessor.KEY_INITIATING_USER, mUserHandle);
146 
147         sendBroadcastToReceiver(intent);
148     }
149 
isDefaultOrSystemDialer(String callingPackageName)150     private boolean isDefaultOrSystemDialer(String callingPackageName) {
151         if (TextUtils.isEmpty(callingPackageName)) {
152             return false;
153         }
154 
155         final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(mContext,
156                 mUserHandle.getIdentifier());
157         if (TextUtils.equals(defaultDialer, callingPackageName)) {
158             return true;
159         }
160 
161         final TelecomManager telecomManager =
162                 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
163         return TextUtils.equals(telecomManager.getSystemDialerPackage(), callingPackageName);
164     }
165 
166     /**
167      * Returns whether the device is voice-capable (e.g. a phone vs a tablet).
168      *
169      * @return {@code True} if the device is voice-capable.
170      */
isVoiceCapable()171     private boolean isVoiceCapable() {
172         return mContext.getApplicationContext().getResources().getBoolean(
173                 com.android.internal.R.bool.config_voice_capable);
174     }
175 
176     /**
177      * Trampolines the intent to the broadcast receiver that runs only as the primary user.
178      */
sendBroadcastToReceiver(Intent intent)179     private boolean sendBroadcastToReceiver(Intent intent) {
180         intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, false);
181         intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
182         intent.setClass(mContext, PrimaryCallReceiver.class);
183         Log.d(this, "Sending broadcast as user to CallReceiver");
184         mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
185         return true;
186     }
187 
showErrorDialogForRestrictedOutgoingCall(Context context, int stringId)188     private static void showErrorDialogForRestrictedOutgoingCall(Context context, int stringId) {
189         final Intent intent = new Intent(context, ErrorDialogActivity.class);
190         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
191         intent.putExtra(ErrorDialogActivity.ERROR_MESSAGE_ID_EXTRA, stringId);
192         context.startActivityAsUser(intent, UserHandle.CURRENT);
193     }
194 }
195