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.compat.annotation.UnsupportedAppUsage; 20 21 import com.android.ims.internal.ConferenceParticipant; 22 import com.android.telephony.Rlog; 23 24 import java.util.ArrayList; 25 import java.util.List; 26 27 /** 28 * {@hide} 29 */ 30 public abstract class Call { 31 protected final String LOG_TAG = "Call"; 32 33 @UnsupportedAppUsage Call()34 public Call() { 35 } 36 37 /* Enums */ 38 @UnsupportedAppUsage(implicitMember = "values()[Lcom/android/internal/telephony/Call$State;") 39 public enum State { 40 @UnsupportedAppUsage 41 IDLE, 42 ACTIVE, 43 @UnsupportedAppUsage 44 HOLDING, 45 @UnsupportedAppUsage 46 DIALING, 47 @UnsupportedAppUsage 48 ALERTING, 49 @UnsupportedAppUsage 50 INCOMING, 51 @UnsupportedAppUsage 52 WAITING, 53 @UnsupportedAppUsage 54 DISCONNECTED, 55 @UnsupportedAppUsage 56 DISCONNECTING; 57 58 @UnsupportedAppUsage isAlive()59 public boolean isAlive() { 60 return !(this == IDLE || this == DISCONNECTED || this == DISCONNECTING); 61 } 62 63 @UnsupportedAppUsage isRinging()64 public boolean isRinging() { 65 return this == INCOMING || this == WAITING; 66 } 67 isDialing()68 public boolean isDialing() { 69 return this == DIALING || this == ALERTING; 70 } 71 } 72 73 public static State stateFromDCState(DriverCall.State dcState)74 stateFromDCState (DriverCall.State dcState) { 75 switch (dcState) { 76 case ACTIVE: return State.ACTIVE; 77 case HOLDING: return State.HOLDING; 78 case DIALING: return State.DIALING; 79 case ALERTING: return State.ALERTING; 80 case INCOMING: return State.INCOMING; 81 case WAITING: return State.WAITING; 82 default: throw new RuntimeException ("illegal call state:" + dcState); 83 } 84 } 85 86 public enum SrvccState { 87 NONE, STARTED, COMPLETED, FAILED, CANCELED; 88 } 89 90 /* Instance Variables */ 91 92 @UnsupportedAppUsage 93 public State mState = State.IDLE; 94 95 @UnsupportedAppUsage 96 public ArrayList<Connection> mConnections = new ArrayList<>(); 97 98 private Object mLock = new Object(); 99 100 /* Instance Methods */ 101 102 /** Do not modify the List result!!! This list is not yours to keep 103 * It will change across event loop iterations top 104 */ 105 106 @UnsupportedAppUsage getConnections()107 public ArrayList<Connection> getConnections() { 108 synchronized (mLock) { 109 return (ArrayList<Connection>) mConnections.clone(); 110 } 111 } 112 113 /** 114 * Get mConnections field from another Call instance. 115 * @param other 116 */ copyConnectionFrom(Call other)117 public void copyConnectionFrom(Call other) { 118 mConnections = other.getConnections(); 119 } 120 121 /** 122 * Get connections count of this instance. 123 * @return the count to return 124 */ getConnectionsCount()125 public int getConnectionsCount() { 126 synchronized (mLock) { 127 return mConnections.size(); 128 } 129 } 130 131 @UnsupportedAppUsage getPhone()132 public abstract Phone getPhone(); 133 @UnsupportedAppUsage isMultiparty()134 public abstract boolean isMultiparty(); 135 @UnsupportedAppUsage hangup()136 public abstract void hangup() throws CallStateException; 137 hangup(@ndroid.telecom.Call.RejectReason int rejectReason)138 public abstract void hangup(@android.telecom.Call.RejectReason int rejectReason) 139 throws CallStateException; 140 141 /** 142 * hasConnection 143 * 144 * @param c a Connection object 145 * @return true if the call contains the connection object passed in 146 */ hasConnection(Connection c)147 public boolean hasConnection(Connection c) { 148 return c.getCall() == this; 149 } 150 151 /** 152 * hasConnections 153 * @return true if the call contains one or more connections 154 */ hasConnections()155 public boolean hasConnections() { 156 List<Connection> connections = getConnections(); 157 158 if (connections == null) { 159 return false; 160 } 161 162 return connections.size() > 0; 163 } 164 165 /** 166 * removeConnection 167 * 168 * @param conn the connection to be removed 169 */ removeConnection(Connection conn)170 public void removeConnection(Connection conn) { 171 synchronized (mLock) { 172 mConnections.remove(conn); 173 } 174 } 175 176 /** 177 * addConnection 178 * 179 * @param conn the connection to be added 180 */ addConnection(Connection conn)181 public void addConnection(Connection conn) { 182 synchronized (mLock) { 183 mConnections.add(conn); 184 } 185 } 186 187 /** 188 * clearConnection 189 */ clearConnections()190 public void clearConnections() { 191 synchronized (mLock) { 192 mConnections.clear(); 193 } 194 } 195 196 /** 197 * getState 198 * @return state of class call 199 */ 200 @UnsupportedAppUsage getState()201 public State getState() { 202 return mState; 203 } 204 205 /** 206 * getConferenceParticipants 207 * @return List of conference participants. 208 */ getConferenceParticipants()209 public List<ConferenceParticipant> getConferenceParticipants() { 210 return null; 211 } 212 213 /** 214 * isIdle 215 * 216 * FIXME rename 217 * @return true if the call contains only disconnected connections (if any) 218 */ 219 @UnsupportedAppUsage isIdle()220 public boolean isIdle() { 221 return !getState().isAlive(); 222 } 223 224 /** 225 * Returns the Connection associated with this Call that was created 226 * first, or null if there are no Connections in this Call 227 */ 228 @UnsupportedAppUsage 229 public Connection getEarliestConnection()230 getEarliestConnection() { 231 List<Connection> l; 232 long time = Long.MAX_VALUE; 233 Connection c; 234 Connection earliest = null; 235 236 l = getConnections(); 237 238 if (l.size() == 0) { 239 return null; 240 } 241 242 for (int i = 0, s = l.size() ; i < s ; i++) { 243 c = l.get(i); 244 long t; 245 246 t = c.getCreateTime(); 247 248 if (t < time) { 249 earliest = c; 250 time = t; 251 } 252 } 253 254 return earliest; 255 } 256 257 public long getEarliestCreateTime()258 getEarliestCreateTime() { 259 List<Connection> l; 260 long time = Long.MAX_VALUE; 261 262 l = getConnections(); 263 264 if (l.size() == 0) { 265 return 0; 266 } 267 268 for (int i = 0, s = l.size() ; i < s ; i++) { 269 Connection c = l.get(i); 270 long t; 271 272 t = c.getCreateTime(); 273 274 time = t < time ? t : time; 275 } 276 277 return time; 278 } 279 280 public long 281 getEarliestConnectTime() { 282 long time = Long.MAX_VALUE; 283 List<Connection> l = getConnections(); 284 285 if (l.size() == 0) { 286 return 0; 287 } 288 289 for (int i = 0, s = l.size() ; i < s ; i++) { 290 Connection c = l.get(i); 291 long t; 292 293 t = c.getConnectTime(); 294 295 time = t < time ? t : time; 296 } 297 298 return time; 299 } 300 301 302 public boolean 303 isDialingOrAlerting() { 304 return getState().isDialing(); 305 } 306 307 public boolean 308 isRinging() { 309 return getState().isRinging(); 310 } 311 312 /** 313 * Returns the Connection associated with this Call that was created 314 * last, or null if there are no Connections in this Call 315 */ 316 @UnsupportedAppUsage 317 public Connection 318 getLatestConnection() { 319 List<Connection> l = getConnections(); 320 if (l.size() == 0) { 321 return null; 322 } 323 324 long time = 0; 325 Connection latest = null; 326 for (int i = 0, s = l.size() ; i < s ; i++) { 327 Connection c = l.get(i); 328 long t = c.getCreateTime(); 329 330 if (t > time) { 331 latest = c; 332 time = t; 333 } 334 } 335 336 return latest; 337 } 338 339 /** 340 * Hangup call if it is alive 341 */ 342 public void hangupIfAlive() { 343 if (getState().isAlive()) { 344 try { 345 hangup(); 346 } catch (CallStateException ex) { 347 Rlog.w(LOG_TAG, " hangupIfActive: caught " + ex); 348 } 349 } 350 } 351 352 /** 353 * Called when it's time to clean up disconnected Connection objects 354 */ 355 public void clearDisconnected() { 356 for (Connection conn : getConnections()) { 357 if (conn.getState() == State.DISCONNECTED) { 358 removeConnection(conn); 359 } 360 } 361 362 if (getConnectionsCount() == 0) { 363 setState(State.IDLE); 364 } 365 } 366 367 protected void setState(State newState) { 368 mState = newState; 369 } 370 } 371