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;
295c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordonimport com.android.internal.telephony.Phone;
30c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordonimport com.android.phone.Constants;
31c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
32c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordonimport java.util.LinkedList;
33c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordonimport java.util.Queue;
346f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal
356f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal/**
366a6e769af983b973a67cff3e8926597525835aa9Ihab Awad * Manages a single phone call handled by CDMA.
376f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal */
383199aa7f8bcb48569eb8289abc055ba0f8496ba8Sailesh Nepalfinal class CdmaConnection extends TelephonyConnection {
39625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn
40a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    private static final int MSG_CALL_WAITING_MISSED = 1;
41c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private static final int MSG_DTMF_SEND_CONFIRMATION = 2;
42a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    private static final int TIMEOUT_CALL_WAITING_MILLIS = 20 * 1000;
43a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
44a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    private final Handler mHandler = new Handler() {
45a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
46a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        /** ${inheritDoc} */
47a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        @Override
48a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        public void handleMessage(Message msg) {
49a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            switch (msg.what) {
50a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                case MSG_CALL_WAITING_MISSED:
51a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    hangupCallWaiting(DisconnectCause.INCOMING_MISSED);
52a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    break;
53c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                case MSG_DTMF_SEND_CONFIRMATION:
54c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                    handleBurstDtmfConfirmation();
55c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                    break;
56a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                default:
57a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    break;
58a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            }
59a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        }
60a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
61a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    };
62a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
63625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn    /**
64625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn     * {@code True} if the CDMA connection should allow mute.
65625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn     */
66625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn    private final boolean mAllowMute;
67a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    private final boolean mIsOutgoing;
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,
805c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon            boolean isOutgoing) {
813199aa7f8bcb48569eb8289abc055ba0f8496ba8Sailesh Nepal        super(connection);
825c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon        mEmergencyTonePlayer = emergencyTonePlayer;
83625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn        mAllowMute = allowMute;
84a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        mIsOutgoing = isOutgoing;
85a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        mIsCallWaiting = connection != null && connection.getState() == Call.State.WAITING;
86a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        if (mIsCallWaiting) {
87a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            startCallWaitingTimer();
88a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        }
896f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal    }
902537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad
912537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    /** {@inheritDoc} */
922537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    @Override
93ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onPlayDtmfTone(char digit) {
94c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        if (useBurstDtmf()) {
95c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            Log.i(this, "sending dtmf digit as burst");
96c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            sendShortDtmfToNetwork(digit);
97c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        } else {
98c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            Log.i(this, "sending dtmf digit directly");
99c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            getPhone().startDtmf(digit);
1003199aa7f8bcb48569eb8289abc055ba0f8496ba8Sailesh Nepal        }
1012537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    }
1022537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad
1032537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    /** {@inheritDoc} */
1042537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    @Override
105ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onStopDtmfTone() {
106c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        if (!useBurstDtmf()) {
107c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            getPhone().stopDtmf();
108c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        }
1092537992d67bb2200bf9e8c69fa97481dfc1db202Ihab Awad    }
110f64d8ca4278e0bfb3afd9023058f86dfc8e92ff6Sailesh Nepal
111f64d8ca4278e0bfb3afd9023058f86dfc8e92ff6Sailesh Nepal    @Override
112a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    public void onReject() {
113a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        Connection connection = getOriginalConnection();
114a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        if (connection != null) {
115a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            switch (connection.getState()) {
116a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                case INCOMING:
117a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    // Normal ringing calls are handled the generic way.
118a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    super.onReject();
119a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    break;
120a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                case WAITING:
121a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    hangupCallWaiting(DisconnectCause.INCOMING_REJECTED);
122a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    break;
123a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                default:
124a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    Log.e(this, new Exception(), "Rejecting a non-ringing call");
125a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    // might as well hang this up, too.
126a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    super.onReject();
127a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                    break;
128a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            }
129a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        }
130a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
131a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
132a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    @Override
133a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    public void onAnswer() {
134a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        mHandler.removeMessages(MSG_CALL_WAITING_MISSED);
135a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        super.onAnswer();
136a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
137a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
13833464599cc0083dba146db75cecea3ee354888c9Tyler Gunn    /**
13933464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     * Clones the current {@link CdmaConnection}.
14033464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     * <p>
14133464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     * Listeners are not copied to the new instance.
14233464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     *
14333464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     * @return The cloned connection.
14433464599cc0083dba146db75cecea3ee354888c9Tyler Gunn     */
14533464599cc0083dba146db75cecea3ee354888c9Tyler Gunn    @Override
14633464599cc0083dba146db75cecea3ee354888c9Tyler Gunn    public TelephonyConnection cloneConnection() {
14733464599cc0083dba146db75cecea3ee354888c9Tyler Gunn        CdmaConnection cdmaConnection = new CdmaConnection(getOriginalConnection(),
14833464599cc0083dba146db75cecea3ee354888c9Tyler Gunn                mEmergencyTonePlayer, mAllowMute, mIsOutgoing);
14933464599cc0083dba146db75cecea3ee354888c9Tyler Gunn        return cdmaConnection;
15033464599cc0083dba146db75cecea3ee354888c9Tyler Gunn    }
15133464599cc0083dba146db75cecea3ee354888c9Tyler Gunn
152a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    @Override
153c927106af6c47ad1f302e13fa8626be83bb46f14Nancy Chen    public void onStateChanged(int state) {
154a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        Connection originalConnection = getOriginalConnection();
155a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        mIsCallWaiting = originalConnection != null &&
156a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                originalConnection.getState() == Call.State.WAITING;
1575c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon
1585c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon        if (state == android.telecom.Connection.STATE_DIALING) {
1595c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon            if (isEmergency()) {
1605c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon                mEmergencyTonePlayer.start();
1615c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon            }
1625c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon        } else {
1635c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon            // No need to check if it is an emergency call, since it is a no-op if it isn't started.
1645c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon            mEmergencyTonePlayer.stop();
1655c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon        }
1665c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon
167c927106af6c47ad1f302e13fa8626be83bb46f14Nancy Chen        super.onStateChanged(state);
168a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
169a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
170a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    @Override
1713cc8121590b5b05af65a9aeaa8948834e4983adcIhab Awad    protected int buildConnectionCapabilities() {
1723cc8121590b5b05af65a9aeaa8948834e4983adcIhab Awad        int capabilities = super.buildConnectionCapabilities();
173625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn        if (mAllowMute) {
1743cc8121590b5b05af65a9aeaa8948834e4983adcIhab Awad            capabilities |= CAPABILITY_MUTE;
175625eb0b8f6e52e7ac1b5a499c5e1964812911913Tyler Gunn        }
176f64d8ca4278e0bfb3afd9023058f86dfc8e92ff6Sailesh Nepal        return capabilities;
177f64d8ca4278e0bfb3afd9023058f86dfc8e92ff6Sailesh Nepal    }
178a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
179cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee    @Override
180cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee    public void performConference(TelephonyConnection otherConnection) {
181cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee        if (isImsConnection()) {
182cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee            super.performConference(otherConnection);
183cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee        } else {
184cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee            Log.w(this, "Non-IMS CDMA Connection attempted to call performConference.");
185cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee        }
186cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee    }
187cb101f68bbaf5a050b422b6cbc29bb20d11078a4Andrew Lee
188a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    void forceAsDialing(boolean isDialing) {
189a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        if (isDialing) {
190a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            setDialing();
191a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        } else {
192a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            updateState();
193a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        }
194a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
195a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
196a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    boolean isOutgoing() {
197a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        return mIsOutgoing;
198a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
199a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
200a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    boolean isCallWaiting() {
201a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        return mIsCallWaiting;
202a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
203a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
204a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    /**
205a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon     * We do not get much in the way of confirmation for Cdma call waiting calls. There is no
206a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon     * indication that a rejected call succeeded, a call waiting call has stopped. Instead we
207a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon     * simulate this for the user. We allow TIMEOUT_CALL_WAITING_MILLIS milliseconds before we
208a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon     * assume that the call was missed and reject it ourselves. reject the call automatically.
209a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon     */
210a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    private void startCallWaitingTimer() {
211a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        mHandler.sendEmptyMessageDelayed(MSG_CALL_WAITING_MISSED, TIMEOUT_CALL_WAITING_MILLIS);
212a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
213a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon
214aef7a4bc4f85149de427d7506ebe97753b2ca6c2Andrew Lee    private void hangupCallWaiting(int telephonyDisconnectCause) {
215a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        Connection originalConnection = getOriginalConnection();
216a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        if (originalConnection != null) {
217a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            try {
218a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                originalConnection.hangup();
219a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            } catch (CallStateException e) {
220a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon                Log.e(this, e, "Failed to hangup call waiting call");
221a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon            }
222aef7a4bc4f85149de427d7506ebe97753b2ca6c2Andrew Lee            setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(telephonyDisconnectCause));
223a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon        }
224a956f73382c3aa2619c73b880a11ee1899c2fe18Santos Cordon    }
225c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
226c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    /**
227c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon     * Read the settings to determine which type of DTMF method this CDMA phone calls.
228c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon     */
229c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private boolean useBurstDtmf() {
2303c96d1a1d0190d99c2c0f3ecf96d09a777d9b32fAndrew Lee        if (isImsConnection()) {
2319ed62ca34427e4f61368f6315f24f563a55b1924Libin.Tang@motorola.com            Log.d(this,"in ims call, return false");
2329ed62ca34427e4f61368f6315f24f563a55b1924Libin.Tang@motorola.com            return false;
2339ed62ca34427e4f61368f6315f24f563a55b1924Libin.Tang@motorola.com        }
234c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        int dtmfTypeSetting = Settings.System.getInt(
235c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                getPhone().getContext().getContentResolver(),
236c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                Settings.System.DTMF_TONE_TYPE_WHEN_DIALING,
237c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                Constants.DTMF_TONE_TYPE_NORMAL);
238c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        return dtmfTypeSetting == Constants.DTMF_TONE_TYPE_NORMAL;
239c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    }
240c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
241c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private void sendShortDtmfToNetwork(char digit) {
242c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        synchronized(mDtmfQueue) {
243c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            if (mDtmfBurstConfirmationPending) {
244c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                mDtmfQueue.add(new Character(digit));
245c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            } else {
246c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                sendBurstDtmfStringLocked(Character.toString(digit));
247c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            }
248c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        }
249c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    }
250c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
251c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private void sendBurstDtmfStringLocked(String dtmfString) {
252c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        getPhone().sendBurstDtmf(
253c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                dtmfString, 0, 0, mHandler.obtainMessage(MSG_DTMF_SEND_CONFIRMATION));
254c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        mDtmfBurstConfirmationPending = true;
255c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    }
256c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
257c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    private void handleBurstDtmfConfirmation() {
258c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        String dtmfDigits = null;
259c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        synchronized(mDtmfQueue) {
260c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            mDtmfBurstConfirmationPending = false;
261c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            if (!mDtmfQueue.isEmpty()) {
262c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                StringBuilder builder = new StringBuilder(mDtmfQueue.size());
263c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                while (!mDtmfQueue.isEmpty()) {
264c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                    builder.append(mDtmfQueue.poll());
265c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                }
266c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                dtmfDigits = builder.toString();
267c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon
268c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                // It would be nice to log the digit, but since DTMF digits can be passwords
269c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                // to things, or other secure account numbers, we want to keep it away from
270c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                // the logs.
271c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                Log.i(this, "%d dtmf character[s] removed from the queue", dtmfDigits.length());
272c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            }
273c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            if (dtmfDigits != null) {
274c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon                sendBurstDtmfStringLocked(dtmfDigits);
275c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon            }
276c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon        }
277c14ca9a77063d42e94d3f6c3f5c090892aa5c8a3Santos Cordon    }
2785c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon
2795c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon    private boolean isEmergency() {
2805c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon        Phone phone = getPhone();
2815c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon        return phone != null &&
2825c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon                PhoneNumberUtils.isLocalEmergencyNumber(
2835c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon                    phone.getContext(), getAddress().getSchemeSpecificPart());
2845c046727927b8cb766ad937bc89687fd1dfd1b4fSantos Cordon    }
2856f342d923df7bbb65ab801ef37bc870459396d59Sailesh Nepal}
286