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