CallList.java revision 7fff6a25f65e0949c8e2682d6470cf065e76a63f
196b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon/*
296b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon * Copyright (C) 2013 The Android Open Source Project
396b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon *
496b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon * Licensed under the Apache License, Version 2.0 (the "License");
596b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon * you may not use this file except in compliance with the License.
696b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon * You may obtain a copy of the License at
796b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon *
896b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon *      http://www.apache.org/licenses/LICENSE-2.0
996b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon *
1096b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon * Unless required by applicable law or agreed to in writing, software
1196b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon * distributed under the License is distributed on an "AS IS" BASIS,
1296b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1396b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon * See the License for the specific language governing permissions and
1496b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon * limitations under the License
1596b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon */
1696b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon
1796b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordonpackage com.android.incallui;
1896b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon
198b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Chengimport com.google.android.collect.Lists;
2096b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordonimport com.google.android.collect.Maps;
21a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordonimport com.google.android.collect.Sets;
2296b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordonimport com.google.common.base.Preconditions;
23671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon
24a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordonimport android.os.Handler;
25a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordonimport android.os.Message;
26a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
2796b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordonimport com.android.services.telephony.common.Call;
2896b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon
2910196fd2f7cc922693e2a7c6c932725a52157943Christine Chenimport java.util.ArrayList;
3096b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordonimport java.util.HashMap;
3196b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordonimport java.util.List;
32a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordonimport java.util.Set;
3396b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon
3496b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon/**
35671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon * Maintains the list of active calls received from CallHandlerService and notifies interested
36671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon * classes of changes to the call list as they are received from the telephony stack.
37671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon * Primary lister of changes to this class is InCallPresenter.
3896b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon */
3996b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordonpublic class CallList {
40671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon
41ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon    private static final int DISCONNECTED_CALL_SHORT_TIMEOUT_MS = 200;
42ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon    private static final int DISCONNECTED_CALL_MEDIUM_TIMEOUT_MS = 2000;
43ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon    private static final int DISCONNECTED_CALL_LONG_TIMEOUT_MS = 5000;
44a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
45a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon    private static final int EVENT_DISCONNECTED_TIMEOUT = 1;
46a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
478b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    private static CallList sInstance = new CallList();
48a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
49a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    private final HashMap<Integer, Call> mCallMap = Maps.newHashMap();
5010196fd2f7cc922693e2a7c6c932725a52157943Christine Chen    private final HashMap<Integer, ArrayList<String>> mCallTextReponsesMap =
5110196fd2f7cc922693e2a7c6c932725a52157943Christine Chen            Maps.newHashMap();
52a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    private final Set<Listener> mListeners = Sets.newArraySet();
538b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    private final HashMap<Integer, List<CallUpdateListener>> mCallUpdateListenerMap = Maps
548b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            .newHashMap();
558b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng
56a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
57a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    /**
58a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     * Static singleton accessor method.
59a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     */
608b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    public static CallList getInstance() {
61a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon        return sInstance;
628b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    }
6396b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon
64a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    /**
65a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     * Private constructor.  Instance should only be acquired through getInstance().
66a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     */
678b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    private CallList() {
68a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    }
6996b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon
70a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    /**
71a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     * Called when a single call has changed.
72a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     */
7396b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon    public void onUpdate(Call call) {
741a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng        Log.d(this, "onUpdate - ", call);
75a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
76a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        updateCallInMap(call);
77a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        notifyListenersOfChange();
78a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon    }
79a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
80a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon    /**
81a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon     * Called when a single call disconnects.
82a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon     */
83a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon    public void onDisconnect(Call call) {
841a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng        Log.d(this, "onDisconnect: ", call);
85a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
867fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        boolean updated = updateCallInMap(call);
8710196fd2f7cc922693e2a7c6c932725a52157943Christine Chen
887fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        if (updated) {
897fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon            // notify those listening for changes on this specific change
907fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon            notifyCallUpdateListeners(call);
917fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon
927fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon            // notify those listening for all disconnects
937fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon            notifyListenersOfDisconnect(call);
947fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        }
9510196fd2f7cc922693e2a7c6c932725a52157943Christine Chen    }
9610196fd2f7cc922693e2a7c6c932725a52157943Christine Chen
9710196fd2f7cc922693e2a7c6c932725a52157943Christine Chen    /**
9810196fd2f7cc922693e2a7c6c932725a52157943Christine Chen     * Called when a single call has changed.
9910196fd2f7cc922693e2a7c6c932725a52157943Christine Chen     */
1008b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    public void onIncoming(Call call, List<String> textMessages) {
1018b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        Log.d(this, "onIncoming - " + call);
10210196fd2f7cc922693e2a7c6c932725a52157943Christine Chen
1038b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        updateCallInMap(call);
1048b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        updateCallTextMap(call, textMessages);
10510196fd2f7cc922693e2a7c6c932725a52157943Christine Chen
1068b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        for (Listener listener : mListeners) {
1078b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            listener.onIncomingCall(call);
1088b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        }
10996b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon    }
11096b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon
111a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    /**
112a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     * Called when multiple calls have changed.
113a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     */
11496b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon    public void onUpdate(List<Call> callsToUpdate) {
1151a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng        Log.d(this, "onUpdate(...)");
116671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon
11796b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon        Preconditions.checkNotNull(callsToUpdate);
11896b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon        for (Call call : callsToUpdate) {
1191a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng            Log.d(this, "\t" + call);
120671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon
12196b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon            updateCallInMap(call);
12210196fd2f7cc922693e2a7c6c932725a52157943Christine Chen            updateCallTextMap(call, null);
1238b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng
1248b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            notifyCallUpdateListeners(call);
12596b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon        }
126a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
127a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon        notifyListenersOfChange();
128a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    }
129a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
1308b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    public void notifyCallUpdateListeners(Call call) {
1318b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        final List<CallUpdateListener> listeners = mCallUpdateListenerMap.get(call.getCallId());
1328b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        if (listeners != null) {
1338b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            for (CallUpdateListener listener : listeners) {
1348b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng                listener.onCallStateChanged(call);
1358b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            }
1368b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        }
1378b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    }
1388b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng
1398b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    /**
1408b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng     * Add a call update listener for a call id.
1418b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng     *
1428b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng     * @param callId The call id to get updates for.
1438b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng     * @param listener The listener to add.
1448b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng     */
1458b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    public void addCallUpdateListener(int callId, CallUpdateListener listener) {
1468b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        List<CallUpdateListener> listeners = mCallUpdateListenerMap.get(callId);
1478b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        if (listeners == null) {
1488b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            listeners = Lists.newArrayList();
1498b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            mCallUpdateListenerMap.put(callId, listeners);
1508b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        }
1518b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        listeners.add(listener);
1528b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    }
1538b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng
1548b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    /**
1558b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng     * Remove a call update listener for a call id.
1568b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng     *
1578b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng     * @param callId The call id to remove the listener for.
1588b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng     * @param listener The listener to remove.
1598b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng     */
1608b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    public void removeCallUpdateListener(int callId, CallUpdateListener listener) {
1618b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        List<CallUpdateListener> listeners = mCallUpdateListenerMap.get(callId);
1628b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        if (listeners != null) {
1638b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            listeners.remove(listener);
1648b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        }
1658b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    }
1668b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng
167a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    public void addListener(Listener listener) {
168a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon        Preconditions.checkNotNull(listener);
169150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon
170a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon        mListeners.add(listener);
171150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon
172150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon        // Let the listener know about the active calls immediately.
173150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon        listener.onCallListChange(this);
174a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    }
175a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
176a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    public void removeListener(Listener listener) {
177a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon        Preconditions.checkNotNull(listener);
178a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon        mListeners.remove(listener);
179a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    }
180a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
181a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    /**
182e7be13fb0556e62b07bc271b130412d82d7f7521Santos Cordon     * TODO: Change so that this function is not needed. Instead of assuming there is an active
183a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     * call, the code should rely on the status of a specific Call and allow the presenters to
184a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     * update the Call object when the active call changes.
185a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     */
186a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    public Call getIncomingOrActive() {
187150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon        Call retval = getIncomingCall();
188150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon        if (retval == null) {
189671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon            retval = getActiveCall();
190150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon        }
191150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon        return retval;
192150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon    }
193150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon
194e7be13fb0556e62b07bc271b130412d82d7f7521Santos Cordon    public Call getOutgoingCall() {
195672b16d0620d033e10fab30ccd70f5dd23e823b7Santos Cordon        Call call = getFirstCallWithState(Call.State.DIALING);
196672b16d0620d033e10fab30ccd70f5dd23e823b7Santos Cordon        if (call == null) {
197672b16d0620d033e10fab30ccd70f5dd23e823b7Santos Cordon            call = getFirstCallWithState(Call.State.REDIALING);
198672b16d0620d033e10fab30ccd70f5dd23e823b7Santos Cordon        }
199672b16d0620d033e10fab30ccd70f5dd23e823b7Santos Cordon        return call;
200e7be13fb0556e62b07bc271b130412d82d7f7521Santos Cordon    }
201e7be13fb0556e62b07bc271b130412d82d7f7521Santos Cordon
202671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon    public Call getActiveCall() {
203671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon        return getFirstCallWithState(Call.State.ACTIVE);
204671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon    }
205671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon
206150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon    public Call getBackgroundCall() {
207150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon        return getFirstCallWithState(Call.State.ONHOLD);
208150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon    }
209150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon
210a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon    public Call getDisconnectedCall() {
211a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        return getFirstCallWithState(Call.State.DISCONNECTED);
212a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon    }
213a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
214ecabb6923e6587e0f0ca98cc895be7d99e694015Christine Chen    public Call getDisconnectingCall() {
215ecabb6923e6587e0f0ca98cc895be7d99e694015Christine Chen        return getFirstCallWithState(Call.State.DISCONNECTING);
216ecabb6923e6587e0f0ca98cc895be7d99e694015Christine Chen    }
217ecabb6923e6587e0f0ca98cc895be7d99e694015Christine Chen
218efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon    public Call getSecondBackgroundCall() {
219efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon        return getCallWithState(Call.State.ONHOLD, 1);
220efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon    }
221efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon
222efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon    public Call getActiveOrBackgroundCall() {
223efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon        Call call = getActiveCall();
224efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon        if (call == null) {
225efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon            call = getBackgroundCall();
226efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon        }
227efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon        return call;
228efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon    }
229efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon
230150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon    public Call getIncomingCall() {
231efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon        Call call = getFirstCallWithState(Call.State.INCOMING);
232efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon        if (call == null) {
233efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon            call = getFirstCallWithState(Call.State.CALL_WAITING);
234efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon        }
235efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon
236efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon        return call;
237150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon    }
238a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
2398b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    public Call getFirstCall() {
2408b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        Call result = getIncomingCall();
2418b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        if (result == null) {
242672b16d0620d033e10fab30ccd70f5dd23e823b7Santos Cordon            result = getOutgoingCall();
2438b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        }
2448b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        if (result == null) {
2458b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            result = getFirstCallWithState(Call.State.ACTIVE);
2468b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        }
2477fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        if (result == null) {
2487fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon            result = getDisconnectingCall();
2497fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        }
2507fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        if (result == null) {
2517fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon            result = getDisconnectedCall();
2527fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        }
2538b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        return result;
2548b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    }
2558b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng
25614dbc3f0ca3a7998c9c5d28aba637487724f529fSantos Cordon    public Call getCall(int callId) {
25714dbc3f0ca3a7998c9c5d28aba637487724f529fSantos Cordon        return mCallMap.get(callId);
25814dbc3f0ca3a7998c9c5d28aba637487724f529fSantos Cordon    }
25914dbc3f0ca3a7998c9c5d28aba637487724f529fSantos Cordon
260150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon    public boolean existsLiveCall() {
261a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon        for (Call call : mCallMap.values()) {
262150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon            if (!isCallDead(call)) {
263150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon                return true;
264150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon            }
265150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon        }
266150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon        return false;
267150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon    }
268150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon
2698b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    public ArrayList<String> getTextResponses(int callId) {
2708b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        return mCallTextReponsesMap.get(callId);
27110196fd2f7cc922693e2a7c6c932725a52157943Christine Chen    }
27210196fd2f7cc922693e2a7c6c932725a52157943Christine Chen
273150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon    /**
274150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon     * Returns first call found in the call map with the specified state.
275150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon     */
276150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon    public Call getFirstCallWithState(int state) {
277efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon        return getCallWithState(state, 0);
278efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon    }
279efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon
280efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon    /**
281efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon     * Returns the [position]th call found in the call map with the specified state.
282046386ed5ae615c8d83bb5a9eccc15e5f79b61ccChristine Chen     * TODO: Improve this logic to sort by call time.
283efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon     */
284efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon    public Call getCallWithState(int state, int positionToFind) {
285150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon        Call retval = null;
286efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon        int position = 0;
287150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon        for (Call call : mCallMap.values()) {
288150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon            if (call.getState() == state) {
289efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon                if (position >= positionToFind) {
290efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon                    retval = call;
291efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon                    break;
292efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon                } else {
293efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon                    position++;
294efd4282ec4221ec5eefd4155a4ad915adcedca70Santos Cordon                }
295a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon            }
296a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon        }
297a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
298a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon        return retval;
299a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    }
300a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
301a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    /**
3023c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon     * This is called when the service disconnects, either expectedly or unexpectedly.
3033c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon     * For the expected case, it's because we have no calls left.  For the unexpected case,
3043c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon     * it is likely a crash of phone and we need to clean up our calls manually.  Without phone,
3053c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon     * there can be no active calls, so this is relatively safe thing to do.
3063c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon     */
3073c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon    public void clearOnDisconnect() {
3083c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon        for (Call call : mCallMap.values()) {
3093c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon            final int state = call.getState();
3103c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon            if (state != Call.State.IDLE &&
3113c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon                    state != Call.State.INVALID &&
3123c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon                    state != Call.State.DISCONNECTED) {
3133c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon                call.setState(Call.State.DISCONNECTED);
3143c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon                updateCallInMap(call);
3153c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon            }
3163c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon        }
3173c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon        notifyListenersOfChange();
3183c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon    }
3193c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon
3203c5581a67ba89fd96fc19e64f6c4780d0a58f640Santos Cordon    /**
321a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     * Sends a generic notification to all listeners that something has changed.
322a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     * It is up to the listeners to call back to determine what changed.
323a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     */
324a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    private void notifyListenersOfChange() {
325a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon        for (Listener listener : mListeners) {
326a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon            listener.onCallListChange(this);
327a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon        }
32896b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon    }
32996b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon
3307fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon    private void notifyListenersOfDisconnect(Call call) {
3317fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        for (Listener listener : mListeners) {
3327fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon            listener.onDisconnect(call);
3337fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        }
3347fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon    }
3357fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon
3367fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon    /**
3377fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon     * Updates the call entry in the local map.
3387fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon     * @return false if no call previously existed and no call was added, otherwise true.
3397fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon     */
3407fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon    private boolean updateCallInMap(Call call) {
34196b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon        Preconditions.checkNotNull(call);
34296b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon
3437fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        boolean updated = false;
3447fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon
34596b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon        final Integer id = new Integer(call.getCallId());
34696b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon
347a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        if (call.getState() == Call.State.DISCONNECTED) {
3481df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon            // update existing (but do not add!!) disconnected calls
3491df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon            if (mCallMap.containsKey(id)) {
350a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
3511df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon                // For disconnected calls, we want to keep them alive for a few seconds so that the
3521df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon                // UI has a chance to display anything it needs when a call is disconnected.
3531df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon
3541df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon                // Set up a timer to destroy the call after X seconds.
3551df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon                final Message msg = mHandler.obtainMessage(EVENT_DISCONNECTED_TIMEOUT, call);
356ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon                mHandler.sendMessageDelayed(msg, getDelayForDisconnect(call));
357a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
358a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon                mCallMap.put(id, call);
3597fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon                updated = true;
360a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon            }
361a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        } else if (!isCallDead(call)) {
362a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon            mCallMap.put(id, call);
3637fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon            updated = true;
364a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon        } else if (mCallMap.containsKey(id)) {
365a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon            mCallMap.remove(id);
3667fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon            updated = true;
36796b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon        }
3687fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon
3697fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        return updated;
37096b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon    }
37196b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon
372ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon    private int getDelayForDisconnect(Call call) {
373ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon        Preconditions.checkState(call.getState() == Call.State.DISCONNECTED);
374ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon
375ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon
376ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon        final Call.DisconnectCause cause = call.getDisconnectCause();
377ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon        final int delay;
378ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon        switch (cause) {
379ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon            case LOCAL:
380ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon                delay = DISCONNECTED_CALL_SHORT_TIMEOUT_MS;
381ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon                break;
382ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon            case NORMAL:
383ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon                delay = DISCONNECTED_CALL_MEDIUM_TIMEOUT_MS;
384ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon                break;
385ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon            case INCOMING_REJECTED:
386ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon            case INCOMING_MISSED:
387ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon                // no delay for missed/rejected incoming calls
388ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon                delay = 0;
389ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon                break;
390ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon            default:
391ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon                delay = DISCONNECTED_CALL_LONG_TIMEOUT_MS;
392ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon                break;
393ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon        }
394ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon
395ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon        return delay;
396ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon    }
397ea83891eb10811d5020cc5fdaf34b711012dab32Santos Cordon
39810196fd2f7cc922693e2a7c6c932725a52157943Christine Chen    private void updateCallTextMap(Call call, List<String> textResponses) {
39910196fd2f7cc922693e2a7c6c932725a52157943Christine Chen        Preconditions.checkNotNull(call);
40010196fd2f7cc922693e2a7c6c932725a52157943Christine Chen
40110196fd2f7cc922693e2a7c6c932725a52157943Christine Chen        final Integer id = new Integer(call.getCallId());
40210196fd2f7cc922693e2a7c6c932725a52157943Christine Chen
40310196fd2f7cc922693e2a7c6c932725a52157943Christine Chen        if (!isCallDead(call)) {
40410196fd2f7cc922693e2a7c6c932725a52157943Christine Chen            if (textResponses != null) {
40510196fd2f7cc922693e2a7c6c932725a52157943Christine Chen                mCallTextReponsesMap.put(id, (ArrayList<String>) textResponses);
40610196fd2f7cc922693e2a7c6c932725a52157943Christine Chen            }
40710196fd2f7cc922693e2a7c6c932725a52157943Christine Chen        } else if (mCallMap.containsKey(id)) {
40810196fd2f7cc922693e2a7c6c932725a52157943Christine Chen            mCallTextReponsesMap.remove(id);
40910196fd2f7cc922693e2a7c6c932725a52157943Christine Chen        }
41010196fd2f7cc922693e2a7c6c932725a52157943Christine Chen    }
41110196fd2f7cc922693e2a7c6c932725a52157943Christine Chen
412a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    private boolean isCallDead(Call call) {
41396b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon        final int state = call.getState();
414a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon        return Call.State.IDLE == state || Call.State.INVALID == state;
415a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    }
416a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
417671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon    /**
418a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon     * Sets up a call for deletion and notifies listeners of change.
419a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon     */
420a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon    private void finishDisconnectedCall(Call call) {
421a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        call.setState(Call.State.IDLE);
422a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        updateCallInMap(call);
423a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        notifyListenersOfChange();
424a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon    }
425a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
426a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon    /**
427a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon     * Handles the timeout for destroying disconnected calls.
428a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon     */
429a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon    private Handler mHandler = new Handler() {
430a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        @Override
431a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        public void handleMessage(Message msg) {
432a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon            switch (msg.what) {
433a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon                case EVENT_DISCONNECTED_TIMEOUT:
4341a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng                    Log.d(this, "EVENT_DISCONNECTED_TIMEOUT ", msg.obj);
435a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon                    finishDisconnectedCall((Call) msg.obj);
436a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon                    break;
437a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon                default:
4381a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng                    Log.wtf(this, "Message not expected: " + msg.what);
439a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon                    break;
440a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon            }
441a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        }
442a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon    };
443a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
444a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon    /**
445a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     * Listener interface for any class that wants to be notified of changes
446a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     * to the call list.
447a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon     */
448a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    public interface Listener {
4497fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        /**
4507fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon         * Called when a new incoming call comes in.
4517fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon         * This is the only method that gets called for incoming calls. Listeners
4527fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon         * that want to perform an action on incoming call should respond in this method
4537fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon         * because {@link #onCallListChange} does not automatically get called for
4547fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon         * incoming calls.
4557fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon         */
4568b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        public void onIncomingCall(Call call);
4577fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon
4587fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        /**
4597fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon         * Called anytime there are changes to the call list.  The change can be switching call
4607fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon         * states, updating information, etc. This method will NOT be called for new incoming
4617fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon         * calls and for calls that switch to disconnected state. Listeners must add actions
4627fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon         * to those method implementations if they want to deal with those actions.
4637fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon         */
4647fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        public void onCallListChange(CallList callList);
4657fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon
4667fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        /**
4677fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon         * Called when a call switches to the disconnected state.  This is the only method
4687fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon         * that will get called upon disconnection.
4697fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon         */
4707fff6a25f65e0949c8e2682d6470cf065e76a63fSantos Cordon        public void onDisconnect(Call call);
4718b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    }
4728b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng
4738b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    public interface CallUpdateListener {
4748b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        // TODO: refactor and limit arg to be call state.  Caller info is not needed.
4758b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        public void onCallStateChanged(Call call);
47696b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon    }
47796b8ba57ac2399336478ffa7a2ccc9423bda0a52Santos Cordon}
478