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