PstnIncomingCallNotifier.java revision 3199aa7f8bcb48569eb8289abc055ba0f8496ba8
12afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon/*
22afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon * Copyright (C) 2014 The Android Open Source Project
32afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon *
42afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon * Licensed under the Apache License, Version 2.0 (the "License");
52afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon * you may not use this file except in compliance with the License.
62afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon * You may obtain a copy of the License at
72afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon *
82afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon *      http://www.apache.org/licenses/LICENSE-2.0
92afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon *
102afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon * Unless required by applicable law or agreed to in writing, software
112afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon * distributed under the License is distributed on an "AS IS" BASIS,
122afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon * See the License for the specific language governing permissions and
142afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon * limitations under the License.
152afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon */
162afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon
172afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordonpackage com.android.services.telephony;
182afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon
19aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordonimport android.content.BroadcastReceiver;
202afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordonimport android.content.Context;
212afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordonimport android.content.Intent;
22aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordonimport android.content.IntentFilter;
233199aa7f8bcb48569eb8289abc055ba0f8496ba8Sailesh Nepalimport android.net.Uri;
242afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordonimport android.os.AsyncResult;
252afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordonimport android.os.Handler;
262afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordonimport android.os.Message;
2773a742ec224ee1f39ba50955e6ffa6130e00297bAmith Yamasaniimport android.os.UserHandle;
282afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordonimport android.telecomm.TelecommConstants;
292afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon
302afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordonimport com.android.internal.telephony.Call;
312afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordonimport com.android.internal.telephony.Connection;
322afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordonimport com.android.internal.telephony.Phone;
33aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordonimport com.android.internal.telephony.PhoneConstants;
34aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordonimport com.android.internal.telephony.PhoneProxy;
35aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordonimport com.android.internal.telephony.TelephonyIntents;
36aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordonimport com.google.common.base.Preconditions;
372afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon
382afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon/**
392afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon * Listens to incoming-call events from the associated phone object and notifies Telecomm upon each
402afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon * occurence. One instance of these exists for each of the telephony-based call services.
412afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon */
42aa7340388473c1676495a60e30dc6a48d318a489Ihab Awadfinal class PstnIncomingCallNotifier {
432afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon    /** New ringing connection event code. */
442afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon    private static final int EVENT_NEW_RINGING_CONNECTION = 100;
452afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon
46aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon    /** The phone proxy object to listen to. */
47aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon    private final PhoneProxy mPhoneProxy;
48aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon
49aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon    /**
50aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     * The base phone implementation behind phone proxy. The underlying phone implementation can
51aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     * change underneath when the radio technology changes. We listen for these events and update
52aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     * the base phone in this variable. We save it so that when the change happens, we can
53aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     * unregister from the events we were listening to.
54aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     */
55aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon    private Phone mPhoneBase;
562afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon
572afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon    /**
58aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     * Used to listen to events from {@link #mPhoneBase}.
592afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon     */
602afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon    private final Handler mHandler = new Handler() {
612afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon        @Override
622afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon        public void handleMessage(Message msg) {
632afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon            switch(msg.what) {
642afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon                case EVENT_NEW_RINGING_CONNECTION:
652afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon                    handleNewRingingConnection((AsyncResult) msg.obj);
662afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon                    break;
672afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon                default:
682afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon                    break;
692afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon            }
702afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon        }
712afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon    };
722afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon
732afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon    /**
74aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     * Receiver to listen for radio technology change events.
75aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     */
76aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon    private final BroadcastReceiver mRATReceiver = new BroadcastReceiver() {
77aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon        @Override
78aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon        public void onReceive(Context context, Intent intent) {
79aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon            String action = intent.getAction();
80aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon            if (TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED.equals(action)) {
81aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon                String newPhone = intent.getStringExtra(PhoneConstants.PHONE_NAME_KEY);
82aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon                Log.d(this, "Radio technology switched. Now %s is active.", newPhone);
83aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon
84aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon                registerForNotifications();
85aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon            }
86aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon        }
87aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon    };
88aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon
89aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon    /**
902afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon     * Persists the specified parameters and starts listening to phone events.
912afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon     *
92aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     * @param phoneProxy The phone object for listening to incoming calls.
932afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon     */
94aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad    PstnIncomingCallNotifier(PhoneProxy phoneProxy) {
95aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon        Preconditions.checkNotNull(phoneProxy);
962afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon
97aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon        mPhoneProxy = phoneProxy;
98aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon
99aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon        registerForNotifications();
100aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon
101aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon        IntentFilter intentFilter =
102aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon                new IntentFilter(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
103aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon        mPhoneProxy.getContext().registerReceiver(mRATReceiver, intentFilter);
104aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon    }
1052afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon
106aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon    /**
107aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     * Register for notifications from the base phone.
108aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     * TODO(santoscordon): We should only need to interact with the phoneproxy directly. However,
109aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     * since the phoneproxy only interacts directly with CallManager we either listen to callmanager
110aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     * or we have to poke into the proxy like this.  Neither is desirable. It would be better if
111aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     * this class and callManager could register generically with the phone proxy instead and get
112aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     * radio techonology changes directly.  Or better yet, just register for the notifications
113aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     * directly with phone proxy and never worry about the technology changes. This requires a
114aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     * change in opt/telephony code.
115aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon     */
116aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon    private void registerForNotifications() {
117aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon        Phone newPhone = mPhoneProxy.getActivePhone();
118aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon        if (newPhone != mPhoneBase) {
119aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon            if (mPhoneBase != null) {
120aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon                Log.i(this, "Unregistering: %s", mPhoneBase);
121aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon                mPhoneBase.unregisterForNewRingingConnection(mHandler);
122aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon            }
123aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon
124aa7340388473c1676495a60e30dc6a48d318a489Ihab Awad            if (newPhone != null) {
125aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon                Log.i(this, "Registering: %s", newPhone);
126aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon                mPhoneBase = newPhone;
127aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon                mPhoneBase.registerForNewRingingConnection(
128aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon                        mHandler, EVENT_NEW_RINGING_CONNECTION, null);
129aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon            }
130aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon        }
1312afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon    }
1322afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon
1332afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon    /**
1342afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon     * Verifies the incoming call and triggers sending the incoming-call intent to Telecomm.
1352afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon     *
1362afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon     * @param asyncResult The result object from the new ringing event.
1372afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon     */
1382afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon    private void handleNewRingingConnection(AsyncResult asyncResult) {
1394822ee866dd3fc138f566afb2da810b491b68a6eSailesh Nepal        Log.d(this, "handleNewRingingConnection");
1402afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon        Connection connection = (Connection) asyncResult.result;
1412afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon        if (connection != null) {
1422afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon            Call call = connection.getCall();
1432afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon
1442afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon            // Final verification of the ringing state before sending the intent to Telecomm.
1452afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon            if (call != null && call.getState().isRinging()) {
1463199aa7f8bcb48569eb8289abc055ba0f8496ba8Sailesh Nepal                sendIncomingCallIntent(connection);
1472afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon            }
1482afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon        }
1492afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon    }
1502afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon
1512afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon    /**
1522afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon     * Sends the incoming call intent to telecomm.
1532afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon     */
1543199aa7f8bcb48569eb8289abc055ba0f8496ba8Sailesh Nepal    private void sendIncomingCallIntent(Connection connection) {
155aac7719aa36cbef5b52ec45aef75005084d60c4aSantos Cordon        Context context = mPhoneProxy.getContext();
1562afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon
1572afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon        Intent intent = new Intent(TelecommConstants.ACTION_INCOMING_CALL);
158c910f9b18fad0a82de96b23fe559825e81b28040Evan Charlton        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1593199aa7f8bcb48569eb8289abc055ba0f8496ba8Sailesh Nepal        intent.putExtra(TelecommConstants.EXTRA_PHONE_ACCOUNT,
1603199aa7f8bcb48569eb8289abc055ba0f8496ba8Sailesh Nepal                TelephonyConnectionService.getPhoneAccount(context));
1612afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon
1624822ee866dd3fc138f566afb2da810b491b68a6eSailesh Nepal        Log.d(this, "Sending incoming call intent: %s", intent);
16373a742ec224ee1f39ba50955e6ffa6130e00297bAmith Yamasani        context.startActivityAsUser(intent, UserHandle.CURRENT);
1642afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon    }
1652afb2bebbb9c88f5ab8752f602a9148e14d14009Santos Cordon}
166