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;
68c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    // Queue of pending short-DTMF characters.
69c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private final Queue<Character> mDtmfQueue = new LinkedList<>();
705c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon    private final EmergencyTonePlayer mEmergencyTonePlayer;
71625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn
72c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    // Indicates that the DTMF confirmation from telephony is pending.
73c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private boolean mDtmfBurstConfirmationPending = false;
74a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    private boolean mIsCallWaiting;
75a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
765c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon    CdmaConnection(
775c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon            Connection connection,
785c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon            EmergencyTonePlayer emergencyTonePlayer,
795c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon            boolean allowMute,
801cf18c55c3764faa21a6690cebe6d09470ed1200Tyler Gunn            boolean isOutgoing,
811cf18c55c3764faa21a6690cebe6d09470ed1200Tyler Gunn            String telecomCallId) {
8257c362606bdc175152c210653a9d613c7572a59eTyler Gunn        super(connection, telecomCallId, isOutgoing);
835c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon        mEmergencyTonePlayer = emergencyTonePlayer;
84625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn        mAllowMute = allowMute;
85a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        mIsCallWaiting = connection != null && connection.getState() == Call.State.WAITING;
86faa1ed26356d75382d512e76244493851e8dcb24Omkar Kolangade        boolean isImsCall = getOriginalConnection() instanceof ImsPhoneConnection;
87faa1ed26356d75382d512e76244493851e8dcb24Omkar Kolangade        // Start call waiting timer for CDMA waiting call.
88faa1ed26356d75382d512e76244493851e8dcb24Omkar Kolangade        if (mIsCallWaiting && !isImsCall) {
89a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            startCallWaitingTimer();
90a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        }
916f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal    }
922537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad
932537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    /** {@inheritDoc} */
942537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    @Override
95ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onPlayDtmfTone(char digit) {
96c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        if (useBurstDtmf()) {
97c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            Log.i(this, "sending dtmf digit as burst");
98c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            sendShortDtmfToNetwork(digit);
99c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        } else {
100c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            Log.i(this, "sending dtmf digit directly");
101c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            getPhone().startDtmf(digit);
1023199aa7f8bcb48569eb8289abc055ba0f8496ba8Sailesh Nepal        }
1032537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    }
1042537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad
1052537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    /** {@inheritDoc} */
1062537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    @Override
107ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onStopDtmfTone() {
108c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        if (!useBurstDtmf()) {
109c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            getPhone().stopDtmf();
110c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        }
1112537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    }
112f64d8ca4278e0bfb3afd9023058f86dfc8e92ff6Sailesh Nepal
113f64d8ca4278e0bfb3afd9023058f86dfc8e92ff6Sailesh Nepal    @Override
114a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    public void onReject() {
115a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        Connection connection = getOriginalConnection();
116a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        if (connection != null) {
117a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            switch (connection.getState()) {
118a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                case INCOMING:
119a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    // Normal ringing calls are handled the generic way.
120a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    super.onReject();
121a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    break;
122a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                case WAITING:
123a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    hangupCallWaiting(DisconnectCause.INCOMING_REJECTED);
124a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    break;
125a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                default:
126a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    Log.e(this, new Exception(), "Rejecting a non-ringing call");
127a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    // might as well hang this up, too.
128a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    super.onReject();
129a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    break;
130a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            }
131a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        }
132a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
133a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
134a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    @Override
135a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    public void onAnswer() {
136a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        mHandler.removeMessages(MSG_CALL_WAITING_MISSED);
137a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        super.onAnswer();
138a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
139a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
14033464599cc0083dba146db75cecea3ee354888c9Tyler Gunn    /**
14133464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     * Clones the current {@link CdmaConnection}.
14233464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     * <p>
14333464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     * Listeners are not copied to the new instance.
14433464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     *
14533464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     * @return The cloned connection.
14633464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     */
14733464599cc0083dba146db75cecea3ee354888c9Tyler Gunn    @Override
14833464599cc0083dba146db75cecea3ee354888c9Tyler Gunn    public TelephonyConnection cloneConnection() {
14933464599cc0083dba146db75cecea3ee354888c9Tyler Gunn        CdmaConnection cdmaConnection = new CdmaConnection(getOriginalConnection(),
1501cf18c55c3764faa21a6690cebe6d09470ed1200Tyler Gunn                mEmergencyTonePlayer, mAllowMute, mIsOutgoing, getTelecomCallId());
15133464599cc0083dba146db75cecea3ee354888c9Tyler Gunn        return cdmaConnection;
15233464599cc0083dba146db75cecea3ee354888c9Tyler Gunn    }
15333464599cc0083dba146db75cecea3ee354888c9Tyler Gunn
154a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    @Override
155c927106af6c47ad1f302e13fa8626be83bb46f14Nancy Chen    public void onStateChanged(int state) {
156a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        Connection originalConnection = getOriginalConnection();
157a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        mIsCallWaiting = originalConnection != null &&
158a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                originalConnection.getState() == Call.State.WAITING;
1595c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon
1603d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar        if (mEmergencyTonePlayer != null) {
1613d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar            if (state == android.telecom.Connection.STATE_DIALING) {
1623d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar                if (isEmergency()) {
1633d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar                    mEmergencyTonePlayer.start();
1643d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar                }
1653d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar            } else {
1663d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar                // No need to check if it is an emergency call, since it is a no-op if it
1673d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar                // isn't started.
1683d8ea0e60c00436c4c3596d83fa164640f10b098Rekha Kumar                mEmergencyTonePlayer.stop();
1695c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon            }
1705c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon        }
1715c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon
172c927106af6c47ad1f302e13fa8626be83bb46f14Nancy Chen        super.onStateChanged(state);
173a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
174a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
175a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    @Override
1763cc8121590b5b05af65a9aeaa8948834e4983adcIhab Awad    protected int buildConnectionCapabilities() {
1773cc8121590b5b05af65a9aeaa8948834e4983adcIhab Awad        int capabilities = super.buildConnectionCapabilities();
178625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn        if (mAllowMute) {
1793cc8121590b5b05af65a9aeaa8948834e4983adcIhab Awad            capabilities |= CAPABILITY_MUTE;
180625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn        }
181f64d8ca4278e0bfb3afd9023058f86dfc8e92ff6Sailesh Nepal        return capabilities;
182f64d8ca4278e0bfb3afd9023058f86dfc8e92ff6Sailesh Nepal    }
183a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
184cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee    @Override
1855149f9cd57ed16f3e4560fc96a0b2b7d1d6095dbTyler Gunn    public void performConference(android.telecom.Connection otherConnection) {
186cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee        if (isImsConnection()) {
187cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee            super.performConference(otherConnection);
188cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee        } else {
189cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee            Log.w(this, "Non-IMS CDMA Connection attempted to call performConference.");
190cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee        }
191cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee    }
192cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee
193a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    void forceAsDialing(boolean isDialing) {
194a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        if (isDialing) {
195bd8589eb7836206246f035edf9c51acef6e6a14bRoshan Pius            setStateOverride(Call.State.DIALING);
196a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        } else {
197bd8589eb7836206246f035edf9c51acef6e6a14bRoshan Pius            resetStateOverride();
198a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        }
199a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
200a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
201a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    boolean isOutgoing() {
202a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        return mIsOutgoing;
203a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
204a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
205a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    boolean isCallWaiting() {
206a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        return mIsCallWaiting;
207a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
208a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
209a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    /**
210a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon     * We do not get much in the way of confirmation for Cdma call waiting calls. There is no
211a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon     * indication that a rejected call succeeded, a call waiting call has stopped. Instead we
212a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon     * simulate this for the user. We allow TIMEOUT_CALL_WAITING_MILLIS milliseconds before we
213a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon     * assume that the call was missed and reject it ourselves. reject the call automatically.
214a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon     */
215a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    private void startCallWaitingTimer() {
216a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        mHandler.sendEmptyMessageDelayed(MSG_CALL_WAITING_MISSED, TIMEOUT_CALL_WAITING_MILLIS);
217a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
218a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
219aef7a4bc4f85149de427d7506ebe97753b2ca6c2Andrew Lee    private void hangupCallWaiting(int telephonyDisconnectCause) {
220a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        Connection originalConnection = getOriginalConnection();
221a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        if (originalConnection != null) {
222a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            try {
223a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                originalConnection.hangup();
224a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            } catch (CallStateException e) {
225a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                Log.e(this, e, "Failed to hangup call waiting call");
226a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            }
227aef7a4bc4f85149de427d7506ebe97753b2ca6c2Andrew Lee            setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(telephonyDisconnectCause));
228a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        }
229a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
230c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
231c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    /**
232c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon     * Read the settings to determine which type of DTMF method this CDMA phone calls.
233c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon     */
234c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private boolean useBurstDtmf() {
2353c96d1a1d0190d99c2c0f3ecf96d09a777d9b32fAndrew Lee        if (isImsConnection()) {
2369ed62ca34427e4f61368f6315f24f563a55b1924Libin.Tang@motorola.com            Log.d(this,"in ims call, return false");
2379ed62ca34427e4f61368f6315f24f563a55b1924Libin.Tang@motorola.com            return false;
2389ed62ca34427e4f61368f6315f24f563a55b1924Libin.Tang@motorola.com        }
239c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        int dtmfTypeSetting = Settings.System.getInt(
240c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                getPhone().getContext().getContentResolver(),
241c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                Settings.System.DTMF_TONE_TYPE_WHEN_DIALING,
242fb7f92eaad86b839bcd94d2814933a151f39a480Andrew Lee                SettingsConstants.DTMF_TONE_TYPE_NORMAL);
243fb7f92eaad86b839bcd94d2814933a151f39a480Andrew Lee        return dtmfTypeSetting == SettingsConstants.DTMF_TONE_TYPE_NORMAL;
244c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    }
245c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
246c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private void sendShortDtmfToNetwork(char digit) {
247c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        synchronized(mDtmfQueue) {
248c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            if (mDtmfBurstConfirmationPending) {
249c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                mDtmfQueue.add(new Character(digit));
250c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            } else {
251c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                sendBurstDtmfStringLocked(Character.toString(digit));
252c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            }
253c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        }
254c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    }
255c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
256c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private void sendBurstDtmfStringLocked(String dtmfString) {
257c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        getPhone().sendBurstDtmf(
258c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                dtmfString, 0, 0, mHandler.obtainMessage(MSG_DTMF_SEND_CONFIRMATION));
259c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        mDtmfBurstConfirmationPending = true;
260c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    }
261c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
262c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private void handleBurstDtmfConfirmation() {
263c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        String dtmfDigits = null;
264c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        synchronized(mDtmfQueue) {
265c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            mDtmfBurstConfirmationPending = false;
266c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            if (!mDtmfQueue.isEmpty()) {
267c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                StringBuilder builder = new StringBuilder(mDtmfQueue.size());
268c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                while (!mDtmfQueue.isEmpty()) {
269c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                    builder.append(mDtmfQueue.poll());
270c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                }
271c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                dtmfDigits = builder.toString();
272c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
273c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                // It would be nice to log the digit, but since DTMF digits can be passwords
274c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                // to things, or other secure account numbers, we want to keep it away from
275c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                // the logs.
276c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                Log.i(this, "%d dtmf character[s] removed from the queue", dtmfDigits.length());
277c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            }
278c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            if (dtmfDigits != null) {
279c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                sendBurstDtmfStringLocked(dtmfDigits);
280c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            }
281c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        }
282c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    }
2835c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon
2845c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon    private boolean isEmergency() {
2855c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon        Phone phone = getPhone();
2865c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon        return phone != null &&
2875c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon                PhoneNumberUtils.isLocalEmergencyNumber(
2885c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon                    phone.getContext(), getAddress().getSchemeSpecificPart());
2895c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon    }
290816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn
291816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn    /**
292816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn     * Called when ECM mode is exited; set the connection to allow mute and update the connection
293816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn     * capabilities.
294816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn     */
295816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn    @Override
296816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn    protected void handleExitedEcmMode() {
297816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn        // We allow mute upon existing ECM mode and rebuild the capabilities.
298816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn        mAllowMute = true;
299816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn        super.handleExitedEcmMode();
300816820e7bcf35be70cf26e534b4767786ff8e83fTyler Gunn    }
3016f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal}
302