ImsExternalCallTracker.java revision da8286bfe1baf68d81a778031d05c3d13fa03f7c
1fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn/*
2fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn * Copyright (C) 2016 The Android Open Source Project
3fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn *
4fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn * Licensed under the Apache License, Version 2.0 (the "License");
5fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn * you may not use this file except in compliance with the License.
6fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn * You may obtain a copy of the License at
7fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn *
8fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn *      http://www.apache.org/licenses/LICENSE-2.0
9fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn *
10fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn * Unless required by applicable law or agreed to in writing, software
11fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn * distributed under the License is distributed on an "AS IS" BASIS,
12fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn * See the License for the specific language governing permissions and
14fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn * limitations under the License
15fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn */
16fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
17fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunnpackage com.android.internal.telephony.imsphone;
18fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
1993da8529345711fd1a5617f3c8b15c0921eececbTyler Gunnimport com.android.ims.ImsCallProfile;
20fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunnimport com.android.ims.ImsExternalCallState;
2193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunnimport com.android.ims.ImsExternalCallStateListener;
22fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunnimport com.android.internal.telephony.Call;
23fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunnimport com.android.internal.telephony.Connection;
24fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunnimport com.android.internal.telephony.Phone;
25fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
26fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunnimport android.os.Bundle;
27fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunnimport android.telecom.PhoneAccountHandle;
28fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunnimport android.util.ArrayMap;
29fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunnimport android.util.Log;
30fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
31fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunnimport java.util.ArrayList;
32fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunnimport java.util.Iterator;
33fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunnimport java.util.List;
34fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunnimport java.util.Map;
35fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
36fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn/**
37fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn * Responsible for tracking external calls known to the system.
38fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn */
39fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunnpublic class ImsExternalCallTracker {
40fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
4193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    /**
4293da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * Implements the {@link ImsExternalCallStateListener}, which is responsible for receiving
4393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * external call state updates from the IMS framework.
4493da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     */
4593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    public class ExternalCallStateListener extends ImsExternalCallStateListener {
4693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        @Override
4793da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        public void onImsExternalCallStateUpdate(List<ImsExternalCallState> externalCallState) {
4893da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn            refreshExternalCallState(externalCallState);
4993da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        }
5093da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    }
5193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn
5293da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    /**
5393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * Receives callbacks from {@link ImsExternalConnection}s when a call pull has been initiated.
5493da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     */
5593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    public class ExternalConnectionListener implements ImsExternalConnection.Listener {
5693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        @Override
5793da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        public void onPullExternalCall(ImsExternalConnection connection) {
5893da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn            Log.d(TAG, "onPullExternalCall: connection = " + connection);
5993da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn            mCallPuller.pullExternalCall(connection.getAddress(), connection.getVideoState());
6093da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        }
6193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    }
6293da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn
63fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    public final static String TAG = "ImsExternalCallTracker";
64fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
65fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    /**
66fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * Extra key used when informing telecom of a new external call using the
67fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * {@link android.telecom.TelecomManager#addNewUnknownCall(PhoneAccountHandle, Bundle)} API.
68fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * Used to ensure that when Telecom requests the {@link android.telecom.ConnectionService} to
69fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * create the connection for the unknown call that we can determine which
70fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * {@link ImsExternalConnection} in {@link #mExternalConnections} is the one being requested.
71fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     */
72fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    public final static String EXTRA_IMS_EXTERNAL_CALL_ID =
73fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn            "android.telephony.ImsExternalCallTracker.extra.EXTERNAL_CALL_ID";
74fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
75fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    /**
76fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * Contains a list of the external connections known by the ImsPhoneCallTracker.  These are
77fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * connections which originated from a dialog event package and reside on another device.
78fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * Used in multi-endpoint (VoLTE for internet connected endpoints) scenarios.
79fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     */
80fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    private Map<Integer, ImsExternalConnection> mExternalConnections =
8193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn            new ArrayMap<>();
8293da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    private final ImsPhone mPhone;
8393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    private final ExternalCallStateListener mExternalCallStateListener;
8493da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    private final ExternalConnectionListener mExternalConnectionListener =
8593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn            new ExternalConnectionListener();
8693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    private final ImsPullCall mCallPuller;
8793da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn
8893da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    public ImsExternalCallTracker(ImsPhone phone, ImsPullCall callPuller) {
89fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        mPhone = phone;
9093da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        mExternalCallStateListener = new ExternalCallStateListener();
9193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        mCallPuller = callPuller;
9293da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    }
9393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn
9493da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    public ExternalCallStateListener getExternalCallStateListener() {
9593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        return mExternalCallStateListener;
96fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    }
97fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
98fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    /**
99fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * Called when the IMS stack receives a new dialog event package.  Triggers the creation and
100fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * update of {@link ImsExternalConnection}s to represent the dialogs in the dialog event
101fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * package data.
102fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     *
103fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * @param externalCallStates the {@link ImsExternalCallState} information for the dialog event
104fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     *                           package.
105fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     */
106fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    public void refreshExternalCallState(List<ImsExternalCallState> externalCallStates) {
107da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn        Log.d(TAG, "refreshExternalCallState");
108fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
109fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        // Check to see if any call Ids are no longer present in the external call state.  If they
110fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        // are, the calls are terminated and should be removed.
111fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        Iterator<Map.Entry<Integer, ImsExternalConnection>> connectionIterator =
112fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn                mExternalConnections.entrySet().iterator();
113fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        boolean wasCallRemoved = false;
114fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        while (connectionIterator.hasNext()) {
115fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn            Map.Entry<Integer, ImsExternalConnection> entry = connectionIterator.next();
116fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn            int callId = entry.getKey().intValue();
117fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
118fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn            if (!containsCallId(externalCallStates, callId)) {
119fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn                ImsExternalConnection externalConnection = entry.getValue();
120fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn                externalConnection.setTerminated();
12193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn                externalConnection.removeListener(mExternalConnectionListener);
122fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn                connectionIterator.remove();
123fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn                wasCallRemoved = true;
124fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn            }
125fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        }
126fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        // If one or more calls were removed, trigger a notification that will cause the
127fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        // TelephonyConnection instancse to refresh their state with Telecom.
128fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        if (wasCallRemoved) {
129fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn            mPhone.notifyPreciseCallStateChanged();
130fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        }
131fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
132fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        // Check for new calls, and updates to existing ones.
133da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn        if (externalCallStates != null && !externalCallStates.isEmpty()) {
134da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn            for (ImsExternalCallState callState : externalCallStates) {
135da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn                if (!mExternalConnections.containsKey(callState.getCallId())) {
136da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn                    Log.d(TAG, "refreshExternalCallState: got = " + callState);
137da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn                    // If there is a new entry and it is already terminated, don't bother adding it to
138da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn                    // telecom.
139da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn                    if (callState.getCallState() != ImsExternalCallState.CALL_STATE_CONFIRMED) {
140da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn                        continue;
141da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn                    }
142da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn                    createExternalConnection(callState);
143da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn                } else {
144da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn                    updateExistingConnection(mExternalConnections.get(callState.getCallId()),
145da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn                            callState);
146fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn                }
147fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn            }
148fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        }
149fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    }
150fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
151fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    /**
152fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * Finds an external connection given a call Id.
153fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     *
154fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * @param callId The call Id.
155fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * @return The {@link Connection}, or {@code null} if no match found.
156fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     */
157fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    public Connection getConnectionById(int callId) {
158fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        return mExternalConnections.get(callId);
159fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    }
160fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
161fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    /**
162fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * Given an {@link ImsExternalCallState} instance obtained from a dialog event package,
163fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * creates a new instance of {@link ImsExternalConnection} to represent the connection, and
164fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * initiates the addition of the new call to Telecom as an unknown call.
165fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     *
166fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * @param state External call state from a dialog event package.
167fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     */
168fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    private void createExternalConnection(ImsExternalCallState state) {
169fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        Log.i(TAG, "createExternalConnection");
170fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
171fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        ImsExternalConnection connection = new ImsExternalConnection(mPhone,
172fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn                state.getCallId(), /* Dialog event package call id */
173fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn                state.getAddress().getSchemeSpecificPart() /* phone number */,
174fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn                state.isCallPullable());
17593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        connection.setVideoState(ImsCallProfile.getVideoStateFromCallType(state.getCallType()));
17693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        connection.addListener(mExternalConnectionListener);
177fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
178fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        // Add to list of tracked connections.
179fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        mExternalConnections.put(connection.getCallId(), connection);
180fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
181fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        // Note: The notification of unknown connection is ultimately handled by
182fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        // PstnIncomingCallNotifier#addNewUnknownCall.  That method will ensure that an extra is set
183fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        // containing the ImsExternalConnection#mCallId so that we have a means of reconciling which
184fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        // unknown call was added.
185fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        mPhone.notifyUnknownConnection(connection);
186fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    }
187fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
188fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    /**
189fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * Given an existing {@link ImsExternalConnection}, applies any changes found found in a
190fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * {@link ImsExternalCallState} instance received from a dialog event package to the connection.
191fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     *
192fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * @param connection The connection to apply changes to.
193fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * @param state The new dialog state for the connection.
194fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     */
195fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    private void updateExistingConnection(ImsExternalConnection connection,
196fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn            ImsExternalCallState state) {
197fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        Call.State existingState = connection.getState();
198fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        Call.State newState = state.getCallState() == ImsExternalCallState.CALL_STATE_CONFIRMED ?
199fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn                Call.State.ACTIVE : Call.State.DISCONNECTED;
200fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
201fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        if (existingState != newState) {
202fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn            if (newState == Call.State.ACTIVE) {
203fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn                connection.setActive();
204fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn            } else {
205fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn                connection.setTerminated();
20693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn                connection.removeListener(mExternalConnectionListener);
207fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn                mExternalConnections.remove(connection);
208fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn                mPhone.notifyPreciseCallStateChanged();
209fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn            }
210fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        }
211fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
212fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        connection.setIsPullable(state.isCallPullable());
21393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn
21493da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        int newVideoState = ImsCallProfile.getVideoStateFromCallType(state.getCallType());
21593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        if (newVideoState != connection.getVideoState()) {
21693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn            connection.setVideoState(newVideoState);
21793da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        }
218fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    }
219fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
220fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    /**
221fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * Determines if a list of call states obtained from a dialog event package contacts an existing
222fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * call Id.
223fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     *
224fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * @param externalCallStates The dialog event package state information.
225fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * @param callId The call Id.
226fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     * @return {@code true} if the state information contains the call Id, {@code false} otherwise.
227fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn     */
228fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    private boolean containsCallId(List<ImsExternalCallState> externalCallStates, int callId) {
229da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn        if (externalCallStates == null) {
230da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn            return false;
231da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn        }
232da8286bfe1baf68d81a778031d05c3d13fa03f7cTyler Gunn
233fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        for (ImsExternalCallState state : externalCallStates) {
234fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn            if (state.getCallId() == callId) {
235fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn                return true;
236fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn            }
237fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        }
238fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn
239fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn        return false;
240fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn    }
241fec523bdc5d2b6dd90212c8076bf34bcc2ab08b2Tyler Gunn}
242