1 /*
2  * Copyright (C) 2006 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 
17 package com.android.internal.telephony;
18 
19 import android.telecom.ConferenceParticipant;
20 
21 import java.util.ArrayList;
22 import java.util.List;
23 
24 import android.telephony.Rlog;
25 
26 /**
27  * {@hide}
28  */
29 public abstract class Call {
30     protected final String LOG_TAG = "Call";
31 
32     /* Enums */
33 
34     public enum State {
35         IDLE, ACTIVE, HOLDING, DIALING, ALERTING, INCOMING, WAITING, DISCONNECTED, DISCONNECTING;
36 
isAlive()37         public boolean isAlive() {
38             return !(this == IDLE || this == DISCONNECTED || this == DISCONNECTING);
39         }
40 
isRinging()41         public boolean isRinging() {
42             return this == INCOMING || this == WAITING;
43         }
44 
isDialing()45         public boolean isDialing() {
46             return this == DIALING || this == ALERTING;
47         }
48     }
49 
50     public static State
stateFromDCState(DriverCall.State dcState)51     stateFromDCState (DriverCall.State dcState) {
52         switch (dcState) {
53             case ACTIVE:        return State.ACTIVE;
54             case HOLDING:       return State.HOLDING;
55             case DIALING:       return State.DIALING;
56             case ALERTING:      return State.ALERTING;
57             case INCOMING:      return State.INCOMING;
58             case WAITING:       return State.WAITING;
59             default:            throw new RuntimeException ("illegal call state:" + dcState);
60         }
61     }
62 
63     public enum SrvccState {
64         NONE, STARTED, COMPLETED, FAILED, CANCELED;
65     }
66 
67     /* Instance Variables */
68 
69     public State mState = State.IDLE;
70 
71     public ArrayList<Connection> mConnections = new ArrayList<Connection>();
72 
73     /* Instance Methods */
74 
75     /** Do not modify the List result!!! This list is not yours to keep
76      *  It will change across event loop iterations            top
77      */
78 
getConnections()79     public abstract List<Connection> getConnections();
getPhone()80     public abstract Phone getPhone();
isMultiparty()81     public abstract boolean isMultiparty();
hangup()82     public abstract void hangup() throws CallStateException;
83 
84 
85     /**
86      * hasConnection
87      *
88      * @param c a Connection object
89      * @return true if the call contains the connection object passed in
90      */
hasConnection(Connection c)91     public boolean hasConnection(Connection c) {
92         return c.getCall() == this;
93     }
94 
95     /**
96      * hasConnections
97      * @return true if the call contains one or more connections
98      */
hasConnections()99     public boolean hasConnections() {
100         List<Connection> connections = getConnections();
101 
102         if (connections == null) {
103             return false;
104         }
105 
106         return connections.size() > 0;
107     }
108 
109     /**
110      * getState
111      * @return state of class call
112      */
getState()113     public State getState() {
114         return mState;
115     }
116 
117     /**
118      * getConferenceParticipants
119      * @return List of conference participants.
120      */
getConferenceParticipants()121     public List<ConferenceParticipant> getConferenceParticipants() {
122         return null;
123     }
124 
125     /**
126      * isIdle
127      *
128      * FIXME rename
129      * @return true if the call contains only disconnected connections (if any)
130      */
isIdle()131     public boolean isIdle() {
132         return !getState().isAlive();
133     }
134 
135     /**
136      * Returns the Connection associated with this Call that was created
137      * first, or null if there are no Connections in this Call
138      */
139     public Connection
getEarliestConnection()140     getEarliestConnection() {
141         List<Connection> l;
142         long time = Long.MAX_VALUE;
143         Connection c;
144         Connection earliest = null;
145 
146         l = getConnections();
147 
148         if (l.size() == 0) {
149             return null;
150         }
151 
152         for (int i = 0, s = l.size() ; i < s ; i++) {
153             c = l.get(i);
154             long t;
155 
156             t = c.getCreateTime();
157 
158             if (t < time) {
159                 earliest = c;
160                 time = t;
161             }
162         }
163 
164         return earliest;
165     }
166 
167     public long
getEarliestCreateTime()168     getEarliestCreateTime() {
169         List<Connection> l;
170         long time = Long.MAX_VALUE;
171 
172         l = getConnections();
173 
174         if (l.size() == 0) {
175             return 0;
176         }
177 
178         for (int i = 0, s = l.size() ; i < s ; i++) {
179             Connection c = l.get(i);
180             long t;
181 
182             t = c.getCreateTime();
183 
184             time = t < time ? t : time;
185         }
186 
187         return time;
188     }
189 
190     public long
191     getEarliestConnectTime() {
192         long time = Long.MAX_VALUE;
193         List<Connection> l = getConnections();
194 
195         if (l.size() == 0) {
196             return 0;
197         }
198 
199         for (int i = 0, s = l.size() ; i < s ; i++) {
200             Connection c = l.get(i);
201             long t;
202 
203             t = c.getConnectTime();
204 
205             time = t < time ? t : time;
206         }
207 
208         return time;
209     }
210 
211 
212     public boolean
213     isDialingOrAlerting() {
214         return getState().isDialing();
215     }
216 
217     public boolean
218     isRinging() {
219         return getState().isRinging();
220     }
221 
222     /**
223      * Returns the Connection associated with this Call that was created
224      * last, or null if there are no Connections in this Call
225      */
226     public Connection
227     getLatestConnection() {
228         List<Connection> l = getConnections();
229         if (l.size() == 0) {
230             return null;
231         }
232 
233         long time = 0;
234         Connection latest = null;
235         for (int i = 0, s = l.size() ; i < s ; i++) {
236             Connection c = l.get(i);
237             long t = c.getCreateTime();
238 
239             if (t > time) {
240                 latest = c;
241                 time = t;
242             }
243         }
244 
245         return latest;
246     }
247 
248     /**
249      * Hangup call if it is alive
250      */
251     public void hangupIfAlive() {
252         if (getState().isAlive()) {
253             try {
254                 hangup();
255             } catch (CallStateException ex) {
256                 Rlog.w(LOG_TAG, " hangupIfActive: caught " + ex);
257             }
258         }
259     }
260 
261     /**
262      * Called when it's time to clean up disconnected Connection objects
263      */
264     public void clearDisconnected() {
265         for (int i = mConnections.size() - 1 ; i >= 0 ; i--) {
266             Connection c = mConnections.get(i);
267             if (c.getState() == State.DISCONNECTED) {
268                 mConnections.remove(i);
269             }
270         }
271 
272         if (mConnections.size() == 0) {
273             setState(State.IDLE);
274         }
275     }
276 
277     protected void setState(State newState) {
278         mState = newState;
279     }
280 }
281