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; 18 19 import android.app.Activity; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.net.Uri; 24 import android.os.Bundle; 25 import android.os.UserHandle; 26 import android.os.UserManager; 27 import android.telecom.PhoneAccount; 28 import android.telecom.PhoneAccountHandle; 29 import android.telecom.TelecomManager; 30 import android.telephony.DisconnectCause; 31 import android.telephony.PhoneNumberUtils; 32 import android.text.TextUtils; 33 import android.widget.Toast; 34 35 // TODO: Needed for move to system service: import com.android.internal.R; 36 37 /** 38 * Activity that handles system CALL actions and forwards them to {@link CallReceiver}. 39 * Handles all three CALL action types: CALL, CALL_PRIVILEGED, and CALL_EMERGENCY. 40 * 41 * Pre-L, the only way apps were were allowed to make outgoing emergency calls was the 42 * ACTION_CALL_PRIVILEGED action (which requires the system only CALL_PRIVILEGED permission). 43 * 44 * In L, any app that has the CALL_PRIVILEGED permission can continue to make outgoing emergency 45 * calls via ACTION_CALL_PRIVILEGED. 46 * 47 * In addition, the default dialer (identified via 48 * {@link android.telecom.TelecomManager#getDefaultPhoneApp()} will also be granted the ability to 49 * make emergency outgoing calls using the CALL action. In order to do this, it must call 50 * startActivityForResult on the CALL intent to allow its package name to be passed to 51 * {@link CallActivity}. Calling startActivity will continue to work on all non-emergency numbers 52 * just like it did pre-L. 53 */ 54 public class CallActivity extends Activity { 55 56 @Override onCreate(Bundle bundle)57 protected void onCreate(Bundle bundle) { 58 super.onCreate(bundle); 59 60 // TODO: Figure out if there is something to restore from bundle. 61 // See OutgoingCallBroadcaster in services/Telephony for more. 62 63 processIntent(getIntent()); 64 65 // This activity does not have associated UI, so close. 66 finish(); 67 Log.d(this, "onCreate: end"); 68 } 69 70 /** 71 * Processes intents sent to the activity. 72 * 73 * @param intent The intent. 74 */ processIntent(Intent intent)75 private void processIntent(Intent intent) { 76 // Ensure call intents are not processed on devices that are not capable of calling. 77 if (!isVoiceCapable()) { 78 return; 79 } 80 81 verifyCallAction(intent); 82 String action = intent.getAction(); 83 84 if (Intent.ACTION_CALL.equals(action) || 85 Intent.ACTION_CALL_PRIVILEGED.equals(action) || 86 Intent.ACTION_CALL_EMERGENCY.equals(action)) { 87 processOutgoingCallIntent(intent); 88 } else if (TelecomManager.ACTION_INCOMING_CALL.equals(action)) { 89 processIncomingCallIntent(intent); 90 } 91 } 92 verifyCallAction(Intent intent)93 private void verifyCallAction(Intent intent) { 94 if (CallActivity.class.getName().equals(intent.getComponent().getClassName())) { 95 // If we were launched directly from the CallActivity, not one of its more privileged 96 // aliases, then make sure that only the non-privileged actions are allowed. 97 if (!Intent.ACTION_CALL.equals(intent.getAction())) { 98 Log.w(this, "Attempt to deliver non-CALL action; forcing to CALL"); 99 intent.setAction(Intent.ACTION_CALL); 100 } 101 } 102 } 103 processOutgoingCallIntent(Intent intent)104 private void processOutgoingCallIntent(Intent intent) { 105 Uri handle = intent.getData(); 106 String scheme = handle.getScheme(); 107 String uriString = handle.getSchemeSpecificPart(); 108 109 if (!PhoneAccount.SCHEME_VOICEMAIL.equals(scheme)) { 110 handle = Uri.fromParts(PhoneNumberUtils.isUriNumber(uriString) ? 111 PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL, uriString, null); 112 } 113 114 UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); 115 if (userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS) 116 && !TelephonyUtil.shouldProcessAsEmergency(this, handle)) { 117 // Only emergency calls are allowed for users with the DISALLOW_OUTGOING_CALLS 118 // restriction. 119 Toast.makeText(this, getResources().getString(R.string.outgoing_call_not_allowed), 120 Toast.LENGTH_SHORT).show(); 121 Log.d(this, "Rejecting non-emergency phone call due to DISALLOW_OUTGOING_CALLS " 122 + "restriction"); 123 return; 124 } 125 126 intent.putExtra(CallReceiver.KEY_IS_DEFAULT_DIALER, isDefaultDialer()); 127 128 if (UserHandle.myUserId() == UserHandle.USER_OWNER) { 129 CallReceiver.processOutgoingCallIntent(getApplicationContext(), intent); 130 } else { 131 sendBroadcastToReceiver(intent, false /* isIncoming */); 132 } 133 } 134 processIncomingCallIntent(Intent intent)135 private void processIncomingCallIntent(Intent intent) { 136 if (UserHandle.myUserId() == UserHandle.USER_OWNER) { 137 CallReceiver.processIncomingCallIntent(intent); 138 } else { 139 sendBroadcastToReceiver(intent, true /* isIncoming */); 140 } 141 } 142 isDefaultDialer()143 private boolean isDefaultDialer() { 144 final String packageName = getCallingPackage(); 145 if (TextUtils.isEmpty(packageName)) { 146 return false; 147 } 148 149 final TelecomManager telecomManager = 150 (TelecomManager) getSystemService(Context.TELECOM_SERVICE); 151 final ComponentName defaultPhoneApp = telecomManager.getDefaultPhoneApp(); 152 return (defaultPhoneApp != null 153 && TextUtils.equals(defaultPhoneApp.getPackageName(), packageName)); 154 } 155 156 /** 157 * Returns whether the device is voice-capable (e.g. a phone vs a tablet). 158 * 159 * @return {@code True} if the device is voice-capable. 160 */ isVoiceCapable()161 private boolean isVoiceCapable() { 162 return getApplicationContext().getResources().getBoolean( 163 com.android.internal.R.bool.config_voice_capable); 164 } 165 166 /** 167 * Trampolines the intent to the broadcast receiver that runs only as the primary user. 168 */ sendBroadcastToReceiver(Intent intent, boolean incoming)169 private boolean sendBroadcastToReceiver(Intent intent, boolean incoming) { 170 intent.putExtra(CallReceiver.KEY_IS_INCOMING_CALL, incoming); 171 intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); 172 intent.setClass(this, CallReceiver.class); 173 Log.d(this, "Sending broadcast as user to CallReceiver- isIncoming: %s", incoming); 174 sendBroadcastAsUser(intent, UserHandle.OWNER); 175 return true; 176 } 177 } 178