1788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal/*
2788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal * Copyright (C) 2014 The Android Open Source Project
3788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal *
4788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal * Licensed under the Apache License, Version 2.0 (the "License");
5788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal * you may not use this file except in compliance with the License.
6788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal * You may obtain a copy of the License at
7788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal *
8788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal *      http://www.apache.org/licenses/LICENSE-2.0
9788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal *
10788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal * Unless required by applicable law or agreed to in writing, software
11788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal * distributed under the License is distributed on an "AS IS" BASIS,
12788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal * See the License for the specific language governing permissions and
14788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal * limitations under the License.
15788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal */
16788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
17788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepalpackage com.android.services.telephony.sip;
18788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
194ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunnimport android.net.Uri;
207877c7255268c34a71c7d1b4055afabb8fcba04cHall Liuimport android.os.Bundle;
211344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepalimport android.os.Handler;
221344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepalimport android.os.Message;
234d45d1cf58a2003378fd35912d6d73a00001bf06Tyler Gunnimport android.telecom.AudioState;
244d45d1cf58a2003378fd35912d6d73a00001bf06Tyler Gunnimport android.telecom.Connection;
254d45d1cf58a2003378fd35912d6d73a00001bf06Tyler Gunnimport android.telecom.PhoneAccount;
267877c7255268c34a71c7d1b4055afabb8fcba04cHall Liuimport android.telecom.TelecomManager;
2706a98183cc79dd112d9d33cf027977a9d5d3418aTyler Gunnimport android.util.EventLog;
28788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepalimport android.util.Log;
29788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
301344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepalimport com.android.internal.telephony.Call;
311344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepalimport com.android.internal.telephony.CallStateException;
327877c7255268c34a71c7d1b4055afabb8fcba04cHall Liuimport com.android.internal.telephony.PhoneConstants;
331344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepalimport com.android.internal.telephony.sip.SipPhone;
34aef7a4bc4f85149de427d7506ebe97753b2ca6c2Andrew Leeimport com.android.services.telephony.DisconnectCauseUtil;
351344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal
364ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunnimport java.util.Objects;
37788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
381344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepalfinal class SipConnection extends Connection {
39788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    private static final String PREFIX = "[SipConnection] ";
406556a09daab949853c384b385bc7618a6c75d9ddSantos Cordon    private static final boolean VERBOSE = false; /* STOP SHIP if true */
41788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
421344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    private static final int MSG_PRECISE_CALL_STATE_CHANGED = 1;
431344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal
441344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    private final Handler mHandler = new Handler() {
451344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        @Override
461344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        public void handleMessage(Message msg) {
471344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            switch (msg.what) {
481344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                case MSG_PRECISE_CALL_STATE_CHANGED:
4922d32b2b81bba31b6ebd93753a5c1ec39e911981Sailesh Nepal                    updateState(false);
501344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                    break;
511344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            }
521344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
531344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    };
541344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal
551344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    private com.android.internal.telephony.Connection mOriginalConnection;
561344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    private Call.State mOriginalConnectionState = Call.State.IDLE;
57788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
58aaf3850172bde1fec1a4558653c0edd31e3fa71fEvan Charlton    SipConnection() {
59aaf3850172bde1fec1a4558653c0edd31e3fa71fEvan Charlton        if (VERBOSE) log("new SipConnection");
60aaf3850172bde1fec1a4558653c0edd31e3fa71fEvan Charlton        setInitializing();
61aaf3850172bde1fec1a4558653c0edd31e3fa71fEvan Charlton    }
62aaf3850172bde1fec1a4558653c0edd31e3fa71fEvan Charlton
63aaf3850172bde1fec1a4558653c0edd31e3fa71fEvan Charlton    void initialize(com.android.internal.telephony.Connection connection) {
64aaf3850172bde1fec1a4558653c0edd31e3fa71fEvan Charlton        if (VERBOSE) log("init SipConnection, connection: " + connection);
651344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        mOriginalConnection = connection;
661344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        if (getPhone() != null) {
671344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            getPhone().registerForPreciseCallStateChanged(mHandler, MSG_PRECISE_CALL_STATE_CHANGED,
681344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                    null);
691344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
7014bf354aab420fcd099cd0209238d7b92dad6f1dAndrew Lee        updateAddress();
717877c7255268c34a71c7d1b4055afabb8fcba04cHall Liu        setTechnologyTypeExtra();
72aaf3850172bde1fec1a4558653c0edd31e3fa71fEvan Charlton        setInitialized();
73788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    }
74788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
75788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    @Override
76c927106af6c47ad1f302e13fa8626be83bb46f14Nancy Chen    public void onAudioStateChanged(AudioState state) {
77c927106af6c47ad1f302e13fa8626be83bb46f14Nancy Chen        if (VERBOSE) log("onAudioStateChanged: " + state);
781344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        if (getPhone() != null) {
791344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            getPhone().setEchoSuppressionEnabled();
801344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
81788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    }
82788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
83788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    @Override
84c927106af6c47ad1f302e13fa8626be83bb46f14Nancy Chen    public void onStateChanged(int state) {
85c927106af6c47ad1f302e13fa8626be83bb46f14Nancy Chen        if (VERBOSE) log("onStateChanged, state: " + Connection.stateToString(state));
86788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    }
87788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
88788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    @Override
89ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onPlayDtmfTone(char c) {
90788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal        if (VERBOSE) log("onPlayDtmfTone");
911344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        if (getPhone() != null) {
921344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            getPhone().startDtmf(c);
931344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
94788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    }
95788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
96788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    @Override
97ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onStopDtmfTone() {
98788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal        if (VERBOSE) log("onStopDtmfTone");
991344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        if (getPhone() != null) {
1001344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            getPhone().stopDtmf();
1011344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
102788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    }
103788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
104788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    @Override
105ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onDisconnect() {
106788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal        if (VERBOSE) log("onDisconnect");
1071344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        try {
1081344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            if (getCall() != null && !getCall().isMultiparty()) {
1091344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                getCall().hangup();
1101344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            } else if (mOriginalConnection != null) {
1111344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                mOriginalConnection.hangup();
1121344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            }
1131344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        } catch (CallStateException e) {
1141344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            log("onDisconnect, exception: " + e);
1151344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
116788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    }
117788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
118788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    @Override
119ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onSeparate() {
120788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal        if (VERBOSE) log("onSeparate");
1211344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        try {
1221344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            if (mOriginalConnection != null) {
1231344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                mOriginalConnection.separate();
1241344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            }
1251344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        } catch (CallStateException e) {
1261344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            log("onSeparate, exception: " + e);
1271344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
128788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    }
129788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
130788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    @Override
131ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onAbort() {
132788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal        if (VERBOSE) log("onAbort");
1331344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        onDisconnect();
134788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    }
135788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
136788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    @Override
137ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onHold() {
138788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal        if (VERBOSE) log("onHold");
1391344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        try {
1402c304ad93f8e74e4a14374d6e00a50cd3497d592Kosuge Yuji            if (getPhone() != null && getState() == STATE_ACTIVE
1412c304ad93f8e74e4a14374d6e00a50cd3497d592Kosuge Yuji                    && getPhone().getRingingCall().getState() != Call.State.WAITING) {
1423ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                // Double check with the internal state since a discrepancy in states could mean
1433ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                // that the transactions is already in progress from a previous request.
1443ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                if (mOriginalConnection != null &&
1453ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                        mOriginalConnection.getState() == Call.State.ACTIVE) {
1463ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                    getPhone().switchHoldingAndActive();
1473ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                } else {
1483ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                    log("skipping switch from onHold due to internal state:");
1493ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                }
1501344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            }
1511344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        } catch (CallStateException e) {
1521344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            log("onHold, exception: " + e);
1531344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
154788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    }
155788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
156788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    @Override
157ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onUnhold() {
158788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal        if (VERBOSE) log("onUnhold");
1591344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        try {
160caf84dca8bd90016d910198f1b178ac03e82dd07Roshan Pius            if (getPhone() != null && getState() == STATE_HOLDING &&
161caf84dca8bd90016d910198f1b178ac03e82dd07Roshan Pius                    getPhone().getForegroundCall().getState() != Call.State.DIALING) {
1623ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                // Double check with the internal state since a discrepancy in states could mean
1633ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                // that the transaction is already in progress from a previous request.
1643ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                if (mOriginalConnection != null &&
1653ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                        mOriginalConnection.getState() == Call.State.HOLDING) {
1663ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                    getPhone().switchHoldingAndActive();
1673ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                } else {
1683ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                    log("skipping switch from onUnHold due to internal state.");
1693ba1419ade788f717dc2beb9667224dc9ed2e317Santos Cordon                }
1701344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            }
1711344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        } catch (CallStateException e) {
1721344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            log("onUnhold, exception: " + e);
1731344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
174788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    }
175788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
176788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    @Override
177ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onAnswer(int videoState) {
178788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal        if (VERBOSE) log("onAnswer");
1791344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        try {
1801344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            if (isValidRingingCall() && getPhone() != null) {
1810bbcc4f2f0218f451a680b98a62c374bba877c3bAndrew Lee                getPhone().acceptCall(videoState);
1821344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            }
1831344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        } catch (CallStateException e) {
1841344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            log("onAnswer, exception: " + e);
18506a98183cc79dd112d9d33cf027977a9d5d3418aTyler Gunn        } catch (IllegalStateException e) {
18606a98183cc79dd112d9d33cf027977a9d5d3418aTyler Gunn            // Call could not be answered due to an invalid audio-codec offered by the caller.  We
18706a98183cc79dd112d9d33cf027977a9d5d3418aTyler Gunn            // will reject the call to stop it from ringing.
18806a98183cc79dd112d9d33cf027977a9d5d3418aTyler Gunn            log("onAnswer, IllegalStateException: " + e);
18906a98183cc79dd112d9d33cf027977a9d5d3418aTyler Gunn            EventLog.writeEvent(0x534e4554, "31752213", -1, "Invalid codec.");
19006a98183cc79dd112d9d33cf027977a9d5d3418aTyler Gunn            onReject();
19106a98183cc79dd112d9d33cf027977a9d5d3418aTyler Gunn        } catch (IllegalArgumentException e) {
19206a98183cc79dd112d9d33cf027977a9d5d3418aTyler Gunn            // Call could not be answered due to an error parsing the SDP.  We will reject the call
19306a98183cc79dd112d9d33cf027977a9d5d3418aTyler Gunn            // to stop it from ringing.
19406a98183cc79dd112d9d33cf027977a9d5d3418aTyler Gunn            log("onAnswer, IllegalArgumentException: " + e);
19506a98183cc79dd112d9d33cf027977a9d5d3418aTyler Gunn            EventLog.writeEvent(0x534e4554, "31752213", -1, "Invalid SDP.");
19606a98183cc79dd112d9d33cf027977a9d5d3418aTyler Gunn            onReject();
1971344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
198788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    }
199788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
200788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    @Override
201ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onReject() {
202788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal        if (VERBOSE) log("onReject");
2031344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        try {
2041344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            if (isValidRingingCall() && getPhone() != null) {
2051344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                getPhone().rejectCall();
2061344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            }
2071344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        } catch (CallStateException e) {
2081344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            log("onReject, exception: " + e);
2091344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
210788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    }
211788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
212788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    @Override
213ab777070da7e83983739414f1222177c6aeebe1aSantos Cordon    public void onPostDialContinue(boolean proceed) {
214788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal        if (VERBOSE) log("onPostDialContinue, proceed: " + proceed);
2151344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        // SIP doesn't have post dial support.
216788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    }
217788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal
2181344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    private Call getCall() {
2191344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        if (mOriginalConnection != null) {
2201344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            return mOriginalConnection.getCall();
2211344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
2221344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        return null;
2231344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    }
2241344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal
2251344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    SipPhone getPhone() {
2261344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        Call call = getCall();
2271344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        if (call != null) {
2281344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            return (SipPhone) call.getPhone();
2291344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
2301344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        return null;
2311344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    }
2321344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal
2331344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    private boolean isValidRingingCall() {
2341344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        Call call = getCall();
2351344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        return call != null && call.getState().isRinging() &&
2361344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                call.getEarliestConnection() == mOriginalConnection;
2371344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    }
2381344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal
23922d32b2b81bba31b6ebd93753a5c1ec39e911981Sailesh Nepal    private void updateState(boolean force) {
2401344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        if (mOriginalConnection == null) {
2411344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            return;
2421344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
2431344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal
2441344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        Call.State newState = mOriginalConnection.getState();
2451344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        if (VERBOSE) log("updateState, " + mOriginalConnectionState + " -> " + newState);
24622d32b2b81bba31b6ebd93753a5c1ec39e911981Sailesh Nepal        if (force || mOriginalConnectionState != newState) {
2471344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            mOriginalConnectionState = newState;
2481344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            switch (newState) {
2491344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                case IDLE:
2501344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                    break;
2511344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                case ACTIVE:
2521344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                    setActive();
2531344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                    break;
2541344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                case HOLDING:
2551344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                    setOnHold();
2561344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                    break;
2571344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                case DIALING:
2581344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                case ALERTING:
2591344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                    setDialing();
260a314b4f398ec4a0f1540c9e437bf2d7f99502b6aAnthony Lee                    // For SIP calls, we need to ask the framework to play the ringback for us.
26114bf354aab420fcd099cd0209238d7b92dad6f1dAndrew Lee                    setRingbackRequested(true);
2621344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                    break;
2631344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                case INCOMING:
2641344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                case WAITING:
2651344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                    setRinging();
2661344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                    break;
2671344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                case DISCONNECTED:
268aef7a4bc4f85149de427d7506ebe97753b2ca6c2Andrew Lee                    setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
269aef7a4bc4f85149de427d7506ebe97753b2ca6c2Andrew Lee                            mOriginalConnection.getDisconnectCause()));
2701344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                    close();
2711344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                    break;
2721344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                case DISCONNECTING:
2731344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal                    break;
2741344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            }
27522d32b2b81bba31b6ebd93753a5c1ec39e911981Sailesh Nepal            updateCallCapabilities(force);
2761344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
2771344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    }
2781344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal
2791344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    private int buildCallCapabilities() {
2803cc8121590b5b05af65a9aeaa8948834e4983adcIhab Awad        int capabilities = CAPABILITY_MUTE | CAPABILITY_SUPPORT_HOLD;
28176f3b4ec8d9bcb8926db1b3e4fb2d1e969b09fbbIhab Awad        if (getState() == STATE_ACTIVE || getState() == STATE_HOLDING) {
2823cc8121590b5b05af65a9aeaa8948834e4983adcIhab Awad            capabilities |= CAPABILITY_HOLD;
2831344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
2841344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        return capabilities;
2851344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    }
2861344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal
28722d32b2b81bba31b6ebd93753a5c1ec39e911981Sailesh Nepal    void updateCallCapabilities(boolean force) {
2881344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        int newCallCapabilities = buildCallCapabilities();
2893cc8121590b5b05af65a9aeaa8948834e4983adcIhab Awad        if (force || getConnectionCapabilities() != newCallCapabilities) {
2903cc8121590b5b05af65a9aeaa8948834e4983adcIhab Awad            setConnectionCapabilities(newCallCapabilities);
2911344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
2921344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    }
2931344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal
2941344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    void onAddedToCallService() {
2951344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        if (VERBOSE) log("onAddedToCallService");
29622d32b2b81bba31b6ebd93753a5c1ec39e911981Sailesh Nepal        updateState(true);
29722d32b2b81bba31b6ebd93753a5c1ec39e911981Sailesh Nepal        updateCallCapabilities(true);
2981344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        setAudioModeIsVoip(true);
2992093a451b17c26f4341e9565b65dcaa0e20bbd7dSailesh Nepal        if (mOriginalConnection != null) {
3002093a451b17c26f4341e9565b65dcaa0e20bbd7dSailesh Nepal            setCallerDisplayName(mOriginalConnection.getCnapName(),
3012093a451b17c26f4341e9565b65dcaa0e20bbd7dSailesh Nepal                    mOriginalConnection.getCnapNamePresentation());
3022093a451b17c26f4341e9565b65dcaa0e20bbd7dSailesh Nepal        }
3031344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    }
3041344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal
3054ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn    /**
3064ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn     * Updates the handle on this connection based on the original connection.
3074ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn     */
30814bf354aab420fcd099cd0209238d7b92dad6f1dAndrew Lee    private void updateAddress() {
3094ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn        if (mOriginalConnection != null) {
31014bf354aab420fcd099cd0209238d7b92dad6f1dAndrew Lee            Uri address = getAddressFromNumber(mOriginalConnection.getAddress());
3114ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn            int presentation = mOriginalConnection.getNumberPresentation();
31214bf354aab420fcd099cd0209238d7b92dad6f1dAndrew Lee            if (!Objects.equals(address, getAddress()) ||
31314bf354aab420fcd099cd0209238d7b92dad6f1dAndrew Lee                    presentation != getAddressPresentation()) {
31414bf354aab420fcd099cd0209238d7b92dad6f1dAndrew Lee                com.android.services.telephony.Log.v(this, "updateAddress, address changed");
31514bf354aab420fcd099cd0209238d7b92dad6f1dAndrew Lee                setAddress(address, presentation);
3164ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn            }
3174ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn
3184ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn            String name = mOriginalConnection.getCnapName();
3194ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn            int namePresentation = mOriginalConnection.getCnapNamePresentation();
3204ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn            if (!Objects.equals(name, getCallerDisplayName()) ||
3214ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn                    namePresentation != getCallerDisplayNamePresentation()) {
3224ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn                com.android.services.telephony.Log
32314bf354aab420fcd099cd0209238d7b92dad6f1dAndrew Lee                        .v(this, "updateAddress, caller display name changed");
3244ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn                setCallerDisplayName(name, namePresentation);
3254ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn            }
3264ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn        }
3274ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn    }
3284ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn
3297877c7255268c34a71c7d1b4055afabb8fcba04cHall Liu    private void setTechnologyTypeExtra() {
3307877c7255268c34a71c7d1b4055afabb8fcba04cHall Liu        int phoneType = PhoneConstants.PHONE_TYPE_SIP;
3317877c7255268c34a71c7d1b4055afabb8fcba04cHall Liu        if (getExtras() == null) {
3327877c7255268c34a71c7d1b4055afabb8fcba04cHall Liu            Bundle b = new Bundle();
3337877c7255268c34a71c7d1b4055afabb8fcba04cHall Liu            b.putInt(TelecomManager.EXTRA_CALL_TECHNOLOGY_TYPE, phoneType);
3347877c7255268c34a71c7d1b4055afabb8fcba04cHall Liu            setExtras(b);
3357877c7255268c34a71c7d1b4055afabb8fcba04cHall Liu        } else {
3367877c7255268c34a71c7d1b4055afabb8fcba04cHall Liu            getExtras().putInt(TelecomManager.EXTRA_CALL_TECHNOLOGY_TYPE, phoneType);
3377877c7255268c34a71c7d1b4055afabb8fcba04cHall Liu        }
3387877c7255268c34a71c7d1b4055afabb8fcba04cHall Liu    }
3397877c7255268c34a71c7d1b4055afabb8fcba04cHall Liu
3404ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn    /**
34114bf354aab420fcd099cd0209238d7b92dad6f1dAndrew Lee     * Determines the address for an incoming number.
3424ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn     *
34314bf354aab420fcd099cd0209238d7b92dad6f1dAndrew Lee     * @param number The incoming number.
3444ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn     * @return The Uri representing the number.
3454ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn     */
34614bf354aab420fcd099cd0209238d7b92dad6f1dAndrew Lee    private static Uri getAddressFromNumber(String number) {
3474ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn        // Address can be null for blocked calls.
34814bf354aab420fcd099cd0209238d7b92dad6f1dAndrew Lee        if (number == null) {
34914bf354aab420fcd099cd0209238d7b92dad6f1dAndrew Lee            number = "";
3504ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn        }
35114bf354aab420fcd099cd0209238d7b92dad6f1dAndrew Lee        return Uri.fromParts(PhoneAccount.SCHEME_SIP, number, null);
3524ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn    }
3534ddd0efe67e93798d98c86b073d6cd0b1343f840Tyler Gunn
3541344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    private void close() {
3551344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        if (getPhone() != null) {
3561344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal            getPhone().unregisterForPreciseCallStateChanged(mHandler);
3571344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        }
3581344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal        mOriginalConnection = null;
3590d5710d9bfdb36d5d0a7be4eaf3f39ae3fb30bc5Evan Charlton        destroy();
3601344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal    }
3611344f67ea331f9a485f54c4b5e26d62a5cfad3fbSailesh Nepal
362788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    private static void log(String msg) {
363788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal        Log.d(SipUtil.LOG_TAG, PREFIX + msg);
364788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal    }
365788959e2d798da2d8a34cf89779421966d200f3dSailesh Nepal}
366