CallList.java revision a012c22dfbfedffe2e751f9b1ab776baa325a26f
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.incallui;
18
19import com.google.android.collect.Lists;
20import com.google.android.collect.Maps;
21import com.google.android.collect.Sets;
22import com.google.common.base.Preconditions;
23import com.google.common.collect.ImmutableList;
24
25import android.util.Log;
26
27import com.android.services.telephony.common.Call;
28
29import java.util.HashMap;
30import java.util.List;
31import java.util.Set;
32
33/**
34 * Maintains the list of active calls received from CallHandlerService.
35 * TODO(klp): This class should be used by InCallUI to read about
36 * changes to calls.
37 */
38public class CallList {
39    private static String TAG = CallList.class.getSimpleName();
40
41    private static CallList sInstance;
42
43    private final HashMap<Integer, Call> mCallMap = Maps.newHashMap();
44    private final Set<Listener> mListeners = Sets.newArraySet();
45
46    /**
47     * Static singleton accessor method.
48     */
49    public static synchronized CallList getInstance() {
50        if (sInstance == null) {
51            sInstance = new CallList();
52        }
53        return sInstance;
54    }
55
56    /**
57     * Private constructor.  Instance should only be acquired through getInstance().
58     */
59    private CallList() {
60    }
61
62    /**
63     * Called when a single call has changed.
64     */
65    public void onUpdate(Call call) {
66        updateCallInMap(call);
67
68        notifyListenersOfChange();
69    }
70
71    /**
72     * Called when multiple calls have changed.
73     */
74    public void onUpdate(List<Call> callsToUpdate) {
75        Preconditions.checkNotNull(callsToUpdate);
76        for (Call call : callsToUpdate) {
77            updateCallInMap(call);
78        }
79
80        notifyListenersOfChange();
81    }
82
83    public void addListener(Listener listener) {
84        Preconditions.checkNotNull(listener);
85        mListeners.add(listener);
86    }
87
88    public void removeListener(Listener listener) {
89        Preconditions.checkNotNull(listener);
90        mListeners.remove(listener);
91    }
92
93    /**
94     * TODO(klp): Change so that this function is not needed. Instead of assuming there is an active
95     * call, the code should rely on the status of a specific Call and allow the presenters to
96     * update the Call object when the active call changes.
97     */
98    public Call getIncomingOrActive() {
99        Call retval = null;
100
101        for (Call call : mCallMap.values()) {
102            if (call.getState() == Call.State.INCOMING) {
103                retval = call;
104                // incoming call takes precedence, cut out early.
105                break;
106            } else if (retval == null && call.getState() == Call.State.ACTIVE) {
107                retval = call;
108            }
109        }
110
111        return retval;
112    }
113
114    /**
115     * Sends a generic notification to all listeners that something has changed.
116     * It is up to the listeners to call back to determine what changed.
117     */
118    private void notifyListenersOfChange() {
119        for (Listener listener : mListeners) {
120            listener.onCallListChange(this);
121        }
122    }
123
124    private void updateCallInMap(Call call) {
125        Preconditions.checkNotNull(call);
126
127        final Integer id = new Integer(call.getCallId());
128
129        if (!isCallDead(call)) {
130            mCallMap.put(id, call);
131        } else if (mCallMap.containsKey(id)) {
132            mCallMap.remove(id);
133        }
134    }
135
136    private boolean isCallDead(Call call) {
137        final int state = call.getState();
138        return Call.State.IDLE == state || Call.State.INVALID == state;
139    }
140
141    /**
142     * Listener interface for any class that wants to be notified of changes
143     * to the call list.
144     */
145    public interface Listener {
146        public void onCallListChange(CallList callList);
147    }
148}
149