OutgoingCallBroadcaster.java revision e9d36b8a17aadd2271db030fc13d0fef01ded7c2
1b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project/* 2b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 4b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * you may not use this file except in compliance with the License. 6b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * You may obtain a copy of the License at 7b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 8b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 10b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * See the License for the specific language governing permissions and 14b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * limitations under the License. 15b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 16b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 17b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectpackage com.android.phone; 18b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 19b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.app.Activity; 20b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.BroadcastReceiver; 21b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.Context; 22b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.Intent; 23b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.net.Uri; 24b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Bundle; 25b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.util.Config; 26b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.Phone; 27b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.telephony.PhoneNumberUtils; 28b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.util.Log; 29b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 30b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project/** 31b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * OutgoingCallBroadcaster receives CALL Intents and sends out broadcast 32b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Intents that allow other applications to monitor, redirect, or prevent 33b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * the outgoing call. If not aborted, the broadcasts will reach 34b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * {@link OutgoingCallReceiver}, and be passed on to {@link InCallScreen}. 35b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 36b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Emergency calls and calls to voicemail when no number is present are 37b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * exempt from being broadcast. 38b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 39b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectpublic class OutgoingCallBroadcaster extends Activity { 40b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 41b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String PERMISSION = android.Manifest.permission.PROCESS_OUTGOING_CALLS; 42b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String TAG = "OutgoingCallBroadcaster"; 43b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final boolean LOGV = Config.LOGV; 44b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 45b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static final String EXTRA_ALREADY_CALLED = "android.phone.extra.ALREADY_CALLED"; 46b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static final String EXTRA_ORIGINAL_URI = "android.phone.extra.ORIGINAL_URI"; 47b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 48b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 49b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project protected void onCreate(Bundle icicle) { 50b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project super.onCreate(icicle); 51b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 52b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent intent = getIntent(); 53b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (LOGV) Log.v(TAG, "onResume: Got intent " + intent + "."); 54b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 55b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String action = intent.getAction(); 56b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = PhoneNumberUtils.getNumberFromIntent(intent, this); 57b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number != null) { 58b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project number = PhoneNumberUtils.convertKeypadLettersToDigits(number); 59b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project number = PhoneNumberUtils.stripSeparators(number); 60b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 61b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final boolean emergencyNumber = 62b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project (number != null) && PhoneNumberUtils.isEmergencyNumber(number); 63b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 64b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean callNow; 65b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 66b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (getClass().getName().equals(intent.getComponent().getClassName())) { 67b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // If we were launched directly from the OutgoingCallBroadcaster, 68b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // not one of its more privileged aliases, then make sure that 69b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // only the non-privileged actions are allowed. 70b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!Intent.ACTION_CALL.equals(intent.getAction())) { 71b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.w(TAG, "Attempt to deliver non-CALL action; forcing to CALL"); 72b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.setAction(Intent.ACTION_CALL); 73b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 74b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 755398ca30f57b928c2dd9bf175c5e083726279494Nicolas Catania 76b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* Change CALL_PRIVILEGED into CALL or CALL_EMERGENCY as needed. */ 77e9d36b8a17aadd2271db030fc13d0fef01ded7c2Nicolas Catania // TODO: This code is redundant with some code in InCallScreen: refactor. 78b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (Intent.ACTION_CALL_PRIVILEGED.equals(action)) { 79b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project action = emergencyNumber 80b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project ? Intent.ACTION_CALL_EMERGENCY 81b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project : Intent.ACTION_CALL; 82b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.setAction(action); 83b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 84b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 85b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (Intent.ACTION_CALL.equals(action)) { 86b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (emergencyNumber) { 87b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.w(TAG, "Cannot call emergency number " + number 88b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project + " with CALL Intent " + intent + "."); 89e9d36b8a17aadd2271db030fc13d0fef01ded7c2Nicolas Catania 90e9d36b8a17aadd2271db030fc13d0fef01ded7c2Nicolas Catania Intent invokeFrameworkDialer = new Intent(); 91e9d36b8a17aadd2271db030fc13d0fef01ded7c2Nicolas Catania 92e9d36b8a17aadd2271db030fc13d0fef01ded7c2Nicolas Catania // TwelveKeyDialer is in a tab so we really want 93e9d36b8a17aadd2271db030fc13d0fef01ded7c2Nicolas Catania // DialtactsActivity. Build the intent 'manually' to 94e9d36b8a17aadd2271db030fc13d0fef01ded7c2Nicolas Catania // use the java resolver to find the dialer class (as 95e9d36b8a17aadd2271db030fc13d0fef01ded7c2Nicolas Catania // opposed to a Context which look up known android 96e9d36b8a17aadd2271db030fc13d0fef01ded7c2Nicolas Catania // packages only) 97e9d36b8a17aadd2271db030fc13d0fef01ded7c2Nicolas Catania // TODO: Don't use DialtactsActivity under the *phone* package, it is cruft. 98e9d36b8a17aadd2271db030fc13d0fef01ded7c2Nicolas Catania invokeFrameworkDialer.setClassName("com.android.contacts", 99e9d36b8a17aadd2271db030fc13d0fef01ded7c2Nicolas Catania "com.android.contacts.DialtactsActivity"); 100e9d36b8a17aadd2271db030fc13d0fef01ded7c2Nicolas Catania invokeFrameworkDialer.setAction(Intent.ACTION_DIAL); 101e9d36b8a17aadd2271db030fc13d0fef01ded7c2Nicolas Catania invokeFrameworkDialer.setData(intent.getData()); 102e9d36b8a17aadd2271db030fc13d0fef01ded7c2Nicolas Catania startActivity(invokeFrameworkDialer); 103b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project finish(); 104b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return; 105b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 106b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callNow = false; 107b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (Intent.ACTION_CALL_EMERGENCY.equals(action)) { 108b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!emergencyNumber) { 109b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.w(TAG, "Cannot call non-emergency number " + number 110b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project + " with EMERGENCY_CALL Intent " + intent + "."); 111b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project finish(); 112b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return; 113b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 114b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callNow = true; 115b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 116b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.e(TAG, "Unhandled Intent " + intent + "."); 117b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project finish(); 118b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return; 119b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 120b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 121b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Make sure the screen is turned on. This is probably the right 122b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // thing to do, and more importantly it works around an issue in the 123b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // activity manager where we will not launch activities consistently 124b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // when the screen is off (since it is trying to keep them paused 125b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // and has... issues). 126b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 127b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Also, this ensures the device stays awake while doing the following 128b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // broadcast; technically we should be holding a wake lock here 129b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // as well. 130b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneApp.getInstance().wakeUpScreen(); 1315398ca30f57b928c2dd9bf175c5e083726279494Nicolas Catania 132b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* If number is null, we're probably trying to call a non-existent voicemail number or 133b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * something else fishy. Whatever the problem, there's no number, so there's no point 134b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * in allowing apps to modify the number. */ 135b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number == null) callNow = true; 136b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 137b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (callNow) { 138b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.setClass(this, InCallScreen.class); 139b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project startActivity(intent); 140b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 141b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 142b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL); 1435398ca30f57b928c2dd9bf175c5e083726279494Nicolas Catania if (number != null) { 1445398ca30f57b928c2dd9bf175c5e083726279494Nicolas Catania broadcastIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number); 1455398ca30f57b928c2dd9bf175c5e083726279494Nicolas Catania } 1467a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania PhoneUtils.copyPhoneProviderExtras(intent, broadcastIntent); 147b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project broadcastIntent.putExtra(EXTRA_ALREADY_CALLED, callNow); 148b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project broadcastIntent.putExtra(EXTRA_ORIGINAL_URI, intent.getData().toString()); 149b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (LOGV) Log.v(TAG, "Broadcasting intent " + broadcastIntent + "."); 150b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendOrderedBroadcast(broadcastIntent, PERMISSION, null, null, 151b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Activity.RESULT_OK, number, null); 152b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 153b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project finish(); 154b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 155b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 156b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project} 157