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