16f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal/*
26f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal * Copyright (C) 2014 The Android Open Source Project
36f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal *
46f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal * Licensed under the Apache License, Version 2.0 (the "License");
56f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal * you may not use this file except in compliance with the License.
66f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal * You may obtain a copy of the License at
76f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal *
86f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal *      http://www.apache.org/licenses/LICENSE-2.0
96f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal *
106f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal * Unless required by applicable law or agreed to in writing, software
116f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal * distributed under the License is distributed on an "AS IS" BASIS,
126f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal * See the License for the specific language governing permissions and
146f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal * limitations under the License.
156f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal */
166f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal
176f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepalpackage com.android.services.telephony;
186f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal
19a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordonimport android.os.Handler;
20a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordonimport android.os.Message;
21f64d8ca4278e0bfb3afd9023058f86dfc8e92ff6Sailesh Nepal
22c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordonimport android.provider.Settings;
23a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordonimport android.telephony.DisconnectCause;
245c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordonimport android.telephony.PhoneNumberUtils;
25a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
26a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordonimport com.android.internal.telephony.Call;
27a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordonimport com.android.internal.telephony.CallStateException;
286a6e769af983b973a67cff3e8926597525835aa9Ihab Awadimport com.android.internal.telephony.Connection;
29faa1ed26356d75382d512e76244493851e8dcb24Omkar Kolangadeimport com.android.internal.telephony.imsphone.ImsPhoneConnection;
305c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordonimport com.android.internal.telephony.Phone;
31fb7f92eaad86b839bcd94d2814933a151f39a480Andrew Leeimport com.android.phone.settings.SettingsConstants;
32c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
33c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordonimport java.util.LinkedList;
34c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordonimport java.util.Queue;
356f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal
366f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal/**
376a6e769af983b973a67cff3e8926597525835aa9Ihab Awad * Manages a single phone call handled by CDMA.
386f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal */
393199aa7f8bcb48569eb8289abc055ba0f8496ba8Sailesh Nepalfinal class CdmaConnection extends TelephonyConnection {
40625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn
41a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    private static final int MSG_CALL_WAITING_MISSED = 1;
42c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private static final int MSG_DTMF_SEND_CONFIRMATION = 2;
43a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    private static final int TIMEOUT_CALL_WAITING_MILLIS = 20 * 1000;
44a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
45a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    private final Handler mHandler = new Handler() {
46a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
47a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        /** ${inheritDoc} */
48a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        @Override
49a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        public void handleMessage(Message msg) {
50a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            switch (msg.what) {
51a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                case MSG_CALL_WAITING_MISSED:
52a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    hangupCallWaiting(DisconnectCause.INCOMING_MISSED);
53a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    break;
54c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                case MSG_DTMF_SEND_CONFIRMATION:
55c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                    handleBurstDtmfConfirmation();
56c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                    break;
57a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                default:
58a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    break;
59a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            }
60a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        }
61a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
62a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    };
63a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
64625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn    /**
65625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn     * {@code True} if the CDMA connection should allow mute.
66625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn     */
67816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn    private boolean mAllowMute;
68a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    private final boolean mIsOutgoing;
69c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    // Queue of pending short-DTMF characters.
70c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private final Queue<Character> mDtmfQueue = new LinkedList<>();
715c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon    private final EmergencyTonePlayer mEmergencyTonePlayer;
72625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn
73c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    // Indicates that the DTMF confirmation from telephony is pending.
74c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private boolean mDtmfBurstConfirmationPending = false;
75a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    private boolean mIsCallWaiting;
76a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
775c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon    CdmaConnection(
785c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon            Connection connection,
795c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon            EmergencyTonePlayer emergencyTonePlayer,
805c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon            boolean allowMute,
811cf18c55c3764faa21a6690cebe6d09470ed1200Tyler Gunn            boolean isOutgoing,
821cf18c55c3764faa21a6690cebe6d09470ed1200Tyler Gunn            String telecomCallId) {
831cf18c55c3764faa21a6690cebe6d09470ed1200Tyler Gunn        super(connection, telecomCallId);
845c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon        mEmergencyTonePlayer = emergencyTonePlayer;
85625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn        mAllowMute = allowMute;
86a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        mIsOutgoing = isOutgoing;
87a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        mIsCallWaiting = connection != null && connection.getState() == Call.State.WAITING;
88faa1ed26356d75382d512e76244493851e8dcb24Omkar Kolangade        boolean isImsCall = getOriginalConnection() instanceof ImsPhoneConnection;
89faa1ed26356d75382d512e76244493851e8dcb24Omkar Kolangade        // Start call waiting timer for CDMA waiting call.
90faa1ed26356d75382d512e76244493851e8dcb24Omkar Kolangade        if (mIsCallWaiting && !isImsCall) {
91a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            startCallWaitingTimer();
92a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        }
936f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal    }
942537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad
952537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    /** {@inheritDoc} */
962537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    @Override
97ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onPlayDtmfTone(char digit) {
98c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        if (useBurstDtmf()) {
99c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            Log.i(this, "sending dtmf digit as burst");
100c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            sendShortDtmfToNetwork(digit);
101c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        } else {
102c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            Log.i(this, "sending dtmf digit directly");
103c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            getPhone().startDtmf(digit);
1043199aa7f8bcb48569eb8289abc055ba0f8496ba8Sailesh Nepal        }
1052537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    }
1062537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad
1072537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    /** {@inheritDoc} */
1082537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    @Override
109ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onStopDtmfTone() {
110c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        if (!useBurstDtmf()) {
111c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            getPhone().stopDtmf();
112c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        }
1132537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    }
114f64d8ca4278e0bfb3afd9023058f86dfc8e92ff6Sailesh Nepal
115f64d8ca4278e0bfb3afd9023058f86dfc8e92ff6Sailesh Nepal    @Override
116a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    public void onReject() {
117a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        Connection connection = getOriginalConnection();
118a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        if (connection != null) {
119a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            switch (connection.getState()) {
120a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                case INCOMING:
121a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    // Normal ringing calls are handled the generic way.
122a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    super.onReject();
123a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    break;
124a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                case WAITING:
125a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    hangupCallWaiting(DisconnectCause.INCOMING_REJECTED);
126a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    break;
127a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                default:
128a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    Log.e(this, new Exception(), "Rejecting a non-ringing call");
129a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    // might as well hang this up, too.
130a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    super.onReject();
131a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    break;
132a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            }
133a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        }
134a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
135a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
136a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    @Override
137a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    public void onAnswer() {
138a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        mHandler.removeMessages(MSG_CALL_WAITING_MISSED);
139a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        super.onAnswer();
140a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
141a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
14233464599cc0083dba146db75cecea3ee354888c9Tyler Gunn    /**
14333464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     * Clones the current {@link CdmaConnection}.
14433464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     * <p>
14533464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     * Listeners are not copied to the new instance.
14633464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     *
14733464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     * @return The cloned connection.
14833464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     */
14933464599cc0083dba146db75cecea3ee354888c9Tyler Gunn    @Override
15033464599cc0083dba146db75cecea3ee354888c9Tyler Gunn    public TelephonyConnection cloneConnection() {
15133464599cc0083dba146db75cecea3ee354888c9Tyler Gunn        CdmaConnection cdmaConnection = new CdmaConnection(getOriginalConnection(),
1521cf18c55c3764faa21a6690cebe6d09470ed1200Tyler Gunn                mEmergencyTonePlayer, mAllowMute, mIsOutgoing, getTelecomCallId());
15333464599cc0083dba146db75cecea3ee354888c9Tyler Gunn        return cdmaConnection;
15433464599cc0083dba146db75cecea3ee354888c9Tyler Gunn    }
15533464599cc0083dba146db75cecea3ee354888c9Tyler Gunn
156a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    @Override
157c927106af6c47ad1f302e13fa8626be83bb46f14Nancy Chen    public void onStateChanged(int state) {
158a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        Connection originalConnection = getOriginalConnection();
159a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        mIsCallWaiting = originalConnection != null &&
160a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                originalConnection.getState() == Call.State.WAITING;
1615c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon
1623d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar        if (mEmergencyTonePlayer != null) {
1633d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar            if (state == android.telecom.Connection.STATE_DIALING) {
1643d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar                if (isEmergency()) {
1653d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar                    mEmergencyTonePlayer.start();
1663d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar                }
1673d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar            } else {
1683d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar                // No need to check if it is an emergency call, since it is a no-op if it
1693d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar                // isn't started.
1703d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar                mEmergencyTonePlayer.stop();
1715c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon            }
1725c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon        }
1735c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon
174c927106af6c47ad1f302e13fa8626be83bb46f14Nancy Chen        super.onStateChanged(state);
175a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
176a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
177a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    @Override
1783cc8121590b5b05af65a9aeaa8948834e4983adcIhab Awad    protected int buildConnectionCapabilities() {
1793cc8121590b5b05af65a9aeaa8948834e4983adcIhab Awad        int capabilities = super.buildConnectionCapabilities();
180625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn        if (mAllowMute) {
1813cc8121590b5b05af65a9aeaa8948834e4983adcIhab Awad            capabilities |= CAPABILITY_MUTE;
182625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn        }
183f64d8ca4278e0bfb3afd9023058f86dfc8e92ff6Sailesh Nepal        return capabilities;
184f64d8ca4278e0bfb3afd9023058f86dfc8e92ff6Sailesh Nepal    }
185a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
186cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee    @Override
1875149f9cd57ed16f3e4560fc96a0b2b7d1d6095dbTyler Gunn    public void performConference(android.telecom.Connection otherConnection) {
188cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee        if (isImsConnection()) {
189cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee            super.performConference(otherConnection);
190cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee        } else {
191cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee            Log.w(this, "Non-IMS CDMA Connection attempted to call performConference.");
192cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee        }
193cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee    }
194cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee
195a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    void forceAsDialing(boolean isDialing) {
196a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        if (isDialing) {
197bd8589eb7836206246f035edf9c51acef6e6a14bRoshan Pius            setStateOverride(Call.State.DIALING);
198a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        } else {
199bd8589eb7836206246f035edf9c51acef6e6a14bRoshan Pius            resetStateOverride();
200a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        }
201a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
202a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
203a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    boolean isOutgoing() {
204a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        return mIsOutgoing;
205a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
206a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
207a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    boolean isCallWaiting() {
208a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        return mIsCallWaiting;
209a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
210a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
211a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    /**
212a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon     * We do not get much in the way of confirmation for Cdma call waiting calls. There is no
213a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon     * indication that a rejected call succeeded, a call waiting call has stopped. Instead we
214a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon     * simulate this for the user. We allow TIMEOUT_CALL_WAITING_MILLIS milliseconds before we
215a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon     * assume that the call was missed and reject it ourselves. reject the call automatically.
216a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon     */
217a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    private void startCallWaitingTimer() {
218a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        mHandler.sendEmptyMessageDelayed(MSG_CALL_WAITING_MISSED, TIMEOUT_CALL_WAITING_MILLIS);
219a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
220a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
221aef7a4bc4f85149de427d7506ebe97753b2ca6c2Andrew Lee    private void hangupCallWaiting(int telephonyDisconnectCause) {
222a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        Connection originalConnection = getOriginalConnection();
223a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        if (originalConnection != null) {
224a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            try {
225a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                originalConnection.hangup();
226a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            } catch (CallStateException e) {
227a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                Log.e(this, e, "Failed to hangup call waiting call");
228a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            }
229aef7a4bc4f85149de427d7506ebe97753b2ca6c2Andrew Lee            setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(telephonyDisconnectCause));
230a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        }
231a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
232c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
233c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    /**
234c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon     * Read the settings to determine which type of DTMF method this CDMA phone calls.
235c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon     */
236c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private boolean useBurstDtmf() {
2373c96d1a1d0190d99c2c0f3ecf96d09a777d9b32fAndrew Lee        if (isImsConnection()) {
2389ed62ca34427e4f61368f6315f24f563a55b1924Libin.Tang@motorola.com            Log.d(this,"in ims call, return false");
2399ed62ca34427e4f61368f6315f24f563a55b1924Libin.Tang@motorola.com            return false;
2409ed62ca34427e4f61368f6315f24f563a55b1924Libin.Tang@motorola.com        }
241c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        int dtmfTypeSetting = Settings.System.getInt(
242c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                getPhone().getContext().getContentResolver(),
243c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                Settings.System.DTMF_TONE_TYPE_WHEN_DIALING,
244fb7f92eaad86b839bcd94d2814933a151f39a480Andrew Lee                SettingsConstants.DTMF_TONE_TYPE_NORMAL);
245fb7f92eaad86b839bcd94d2814933a151f39a480Andrew Lee        return dtmfTypeSetting == SettingsConstants.DTMF_TONE_TYPE_NORMAL;
246c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    }
247c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
248c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private void sendShortDtmfToNetwork(char digit) {
249c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        synchronized(mDtmfQueue) {
250c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            if (mDtmfBurstConfirmationPending) {
251c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                mDtmfQueue.add(new Character(digit));
252c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            } else {
253c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                sendBurstDtmfStringLocked(Character.toString(digit));
254c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            }
255c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        }
256c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    }
257c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
258c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private void sendBurstDtmfStringLocked(String dtmfString) {
259c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        getPhone().sendBurstDtmf(
260c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                dtmfString, 0, 0, mHandler.obtainMessage(MSG_DTMF_SEND_CONFIRMATION));
261c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        mDtmfBurstConfirmationPending = true;
262c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    }
263c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
264c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private void handleBurstDtmfConfirmation() {
265c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        String dtmfDigits = null;
266c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        synchronized(mDtmfQueue) {
267c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            mDtmfBurstConfirmationPending = false;
268c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            if (!mDtmfQueue.isEmpty()) {
269c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                StringBuilder builder = new StringBuilder(mDtmfQueue.size());
270c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                while (!mDtmfQueue.isEmpty()) {
271c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                    builder.append(mDtmfQueue.poll());
272c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                }
273c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                dtmfDigits = builder.toString();
274c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
275c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                // It would be nice to log the digit, but since DTMF digits can be passwords
276c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                // to things, or other secure account numbers, we want to keep it away from
277c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                // the logs.
278c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                Log.i(this, "%d dtmf character[s] removed from the queue", dtmfDigits.length());
279c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            }
280c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            if (dtmfDigits != null) {
281c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                sendBurstDtmfStringLocked(dtmfDigits);
282c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            }
283c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        }
284c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    }
2855c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon
2865c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon    private boolean isEmergency() {
2875c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon        Phone phone = getPhone();
2885c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon        return phone != null &&
2895c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon                PhoneNumberUtils.isLocalEmergencyNumber(
2905c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon                    phone.getContext(), getAddress().getSchemeSpecificPart());
2915c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon    }
292816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn
293816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn    /**
294816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn     * Called when ECM mode is exited; set the connection to allow mute and update the connection
295816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn     * capabilities.
296816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn     */
297816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn    @Override
298816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn    protected void handleExitedEcmMode() {
299816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn        // We allow mute upon existing ECM mode and rebuild the capabilities.
300816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn        mAllowMute = true;
301816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn        super.handleExitedEcmMode();
302816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn    }
3036f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal}
304