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.net.Uri; 20 import android.os.SystemClock; 21 import android.telecom.ConferenceParticipant; 22 import android.telephony.Rlog; 23 import android.util.Log; 24 25 import java.lang.Override; 26 import java.util.ArrayList; 27 import java.util.List; 28 import java.util.Set; 29 import java.util.concurrent.CopyOnWriteArraySet; 30 31 /** 32 * {@hide} 33 */ 34 public abstract class Connection { 35 public interface PostDialListener { onPostDialWait()36 void onPostDialWait(); onPostDialChar(char c)37 void onPostDialChar(char c); 38 } 39 40 /** 41 * Listener interface for events related to the connection which should be reported to the 42 * {@link android.telecom.Connection}. 43 */ 44 public interface Listener { onVideoStateChanged(int videoState)45 public void onVideoStateChanged(int videoState); onLocalVideoCapabilityChanged(boolean capable)46 public void onLocalVideoCapabilityChanged(boolean capable); onRemoteVideoCapabilityChanged(boolean capable)47 public void onRemoteVideoCapabilityChanged(boolean capable); onVideoProviderChanged( android.telecom.Connection.VideoProvider videoProvider)48 public void onVideoProviderChanged( 49 android.telecom.Connection.VideoProvider videoProvider); onAudioQualityChanged(int audioQuality)50 public void onAudioQualityChanged(int audioQuality); onConferenceParticipantsChanged(List<ConferenceParticipant> participants)51 public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants); 52 } 53 54 /** 55 * Base listener implementation. 56 */ 57 public abstract static class ListenerBase implements Listener { 58 @Override onVideoStateChanged(int videoState)59 public void onVideoStateChanged(int videoState) {} 60 @Override onLocalVideoCapabilityChanged(boolean capable)61 public void onLocalVideoCapabilityChanged(boolean capable) {} 62 @Override onRemoteVideoCapabilityChanged(boolean capable)63 public void onRemoteVideoCapabilityChanged(boolean capable) {} 64 @Override onVideoProviderChanged( android.telecom.Connection.VideoProvider videoProvider)65 public void onVideoProviderChanged( 66 android.telecom.Connection.VideoProvider videoProvider) {} 67 @Override onAudioQualityChanged(int audioQuality)68 public void onAudioQualityChanged(int audioQuality) {} 69 @Override onConferenceParticipantsChanged(List<ConferenceParticipant> participants)70 public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants) {} 71 } 72 73 public static final int AUDIO_QUALITY_STANDARD = 1; 74 public static final int AUDIO_QUALITY_HIGH_DEFINITION = 2; 75 76 //Caller Name Display 77 protected String mCnapName; 78 protected int mCnapNamePresentation = PhoneConstants.PRESENTATION_ALLOWED; 79 protected String mAddress; // MAY BE NULL!!! 80 protected String mDialString; // outgoing calls only 81 protected int mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED; 82 protected boolean mIsIncoming; 83 /* 84 * These time/timespan values are based on System.currentTimeMillis(), 85 * i.e., "wall clock" time. 86 */ 87 protected long mCreateTime; 88 protected long mConnectTime; 89 /* 90 * These time/timespan values are based on SystemClock.elapsedRealTime(), 91 * i.e., time since boot. They are appropriate for comparison and 92 * calculating deltas. 93 */ 94 protected long mConnectTimeReal; 95 protected long mDuration; 96 protected long mHoldingStartTime; // The time when the Connection last transitioned 97 // into HOLDING 98 protected Connection mOrigConnection; 99 private List<PostDialListener> mPostDialListeners = new ArrayList<>(); 100 public Set<Listener> mListeners = new CopyOnWriteArraySet<>(); 101 102 protected boolean mNumberConverted = false; 103 protected String mConvertedNumber; 104 105 private static String LOG_TAG = "Connection"; 106 107 Object mUserData; 108 private int mVideoState; 109 private boolean mLocalVideoCapable; 110 private boolean mRemoteVideoCapable; 111 private int mAudioQuality; 112 private android.telecom.Connection.VideoProvider mVideoProvider; 113 public Call.State mPreHandoverState = Call.State.IDLE; 114 115 /* Instance Methods */ 116 117 /** 118 * Gets address (e.g. phone number) associated with connection. 119 * TODO: distinguish reasons for unavailability 120 * 121 * @return address or null if unavailable 122 */ 123 getAddress()124 public String getAddress() { 125 return mAddress; 126 } 127 128 /** 129 * Gets CNAP name associated with connection. 130 * @return cnap name or null if unavailable 131 */ getCnapName()132 public String getCnapName() { 133 return mCnapName; 134 } 135 136 /** 137 * Get original dial string. 138 * @return original dial string or null if unavailable 139 */ getOrigDialString()140 public String getOrigDialString(){ 141 return null; 142 } 143 144 /** 145 * Gets CNAP presentation associated with connection. 146 * @return cnap name or null if unavailable 147 */ 148 getCnapNamePresentation()149 public int getCnapNamePresentation() { 150 return mCnapNamePresentation; 151 } 152 153 /** 154 * @return Call that owns this Connection, or null if none 155 */ getCall()156 public abstract Call getCall(); 157 158 /** 159 * Connection create time in currentTimeMillis() format 160 * Basically, set when object is created. 161 * Effectively, when an incoming call starts ringing or an 162 * outgoing call starts dialing 163 */ getCreateTime()164 public long getCreateTime() { 165 return mCreateTime; 166 } 167 168 /** 169 * Connection connect time in currentTimeMillis() format. 170 * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition. 171 * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition. 172 * Returns 0 before then. 173 */ getConnectTime()174 public long getConnectTime() { 175 return mConnectTime; 176 } 177 178 /** 179 * Sets the Connection connect time in currentTimeMillis() format. 180 * 181 * @param connectTime the new connect time. 182 */ setConnectTime(long connectTime)183 public void setConnectTime(long connectTime) { 184 mConnectTime = connectTime; 185 } 186 187 /** 188 * Connection connect time in elapsedRealtime() format. 189 * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition. 190 * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition. 191 * Returns 0 before then. 192 */ getConnectTimeReal()193 public long getConnectTimeReal() { 194 return mConnectTimeReal; 195 } 196 197 /** 198 * Disconnect time in currentTimeMillis() format. 199 * The time when this Connection makes a transition into ENDED or FAIL. 200 * Returns 0 before then. 201 */ getDisconnectTime()202 public abstract long getDisconnectTime(); 203 204 /** 205 * Returns the number of milliseconds the call has been connected, 206 * or 0 if the call has never connected. 207 * If the call is still connected, then returns the elapsed 208 * time since connect. 209 */ getDurationMillis()210 public long getDurationMillis() { 211 if (mConnectTimeReal == 0) { 212 return 0; 213 } else if (mDuration == 0) { 214 return SystemClock.elapsedRealtime() - mConnectTimeReal; 215 } else { 216 return mDuration; 217 } 218 } 219 220 /** 221 * The time when this Connection last transitioned into HOLDING 222 * in elapsedRealtime() format. 223 * Returns 0, if it has never made a transition into HOLDING. 224 */ getHoldingStartTime()225 public long getHoldingStartTime() { 226 return mHoldingStartTime; 227 } 228 229 /** 230 * If this connection is HOLDING, return the number of milliseconds 231 * that it has been on hold for (approximately). 232 * If this connection is in any other state, return 0. 233 */ 234 getHoldDurationMillis()235 public abstract long getHoldDurationMillis(); 236 237 /** 238 * Returns call disconnect cause. Values are defined in 239 * {@link android.telephony.DisconnectCause}. If the call is not yet 240 * disconnected, NOT_DISCONNECTED is returned. 241 */ getDisconnectCause()242 public abstract int getDisconnectCause(); 243 244 /** 245 * Returns true of this connection originated elsewhere 246 * ("MT" or mobile terminated; another party called this terminal) 247 * or false if this call originated here (MO or mobile originated). 248 */ isIncoming()249 public boolean isIncoming() { 250 return mIsIncoming; 251 } 252 253 /** 254 * If this Connection is connected, then it is associated with 255 * a Call. 256 * 257 * Returns getCall().getState() or Call.State.IDLE if not 258 * connected 259 */ getState()260 public Call.State getState() { 261 Call c; 262 263 c = getCall(); 264 265 if (c == null) { 266 return Call.State.IDLE; 267 } else { 268 return c.getState(); 269 } 270 } 271 272 /** 273 * If this connection went through handover return the state of the 274 * call that contained this connection before handover. 275 */ getStateBeforeHandover()276 public Call.State getStateBeforeHandover() { 277 return mPreHandoverState; 278 } 279 280 /** 281 * isAlive() 282 * 283 * @return true if the connection isn't disconnected 284 * (could be active, holding, ringing, dialing, etc) 285 */ 286 public boolean isAlive()287 isAlive() { 288 return getState().isAlive(); 289 } 290 291 /** 292 * Returns true if Connection is connected and is INCOMING or WAITING 293 */ 294 public boolean isRinging()295 isRinging() { 296 return getState().isRinging(); 297 } 298 299 /** 300 * 301 * @return the userdata set in setUserData() 302 */ getUserData()303 public Object getUserData() { 304 return mUserData; 305 } 306 307 /** 308 * 309 * @param userdata user can store an any userdata in the Connection object. 310 */ setUserData(Object userdata)311 public void setUserData(Object userdata) { 312 mUserData = userdata; 313 } 314 315 /** 316 * Hangup individual Connection 317 */ hangup()318 public abstract void hangup() throws CallStateException; 319 320 /** 321 * Separate this call from its owner Call and assigns it to a new Call 322 * (eg if it is currently part of a Conference call 323 * TODO: Throw exception? Does GSM require error display on failure here? 324 */ separate()325 public abstract void separate() throws CallStateException; 326 327 public enum PostDialState { 328 NOT_STARTED, /* The post dial string playback hasn't 329 been started, or this call is not yet 330 connected, or this is an incoming call */ 331 STARTED, /* The post dial string playback has begun */ 332 WAIT, /* The post dial string playback is waiting for a 333 call to proceedAfterWaitChar() */ 334 WILD, /* The post dial string playback is waiting for a 335 call to proceedAfterWildChar() */ 336 COMPLETE, /* The post dial string playback is complete */ 337 CANCELLED, /* The post dial string playback was cancelled 338 with cancelPostDial() */ 339 PAUSE /* The post dial string playback is pausing for a 340 call to processNextPostDialChar*/ 341 } 342 clearUserData()343 public void clearUserData(){ 344 mUserData = null; 345 } 346 addPostDialListener(PostDialListener listener)347 public final void addPostDialListener(PostDialListener listener) { 348 if (!mPostDialListeners.contains(listener)) { 349 mPostDialListeners.add(listener); 350 } 351 } 352 clearPostDialListeners()353 protected final void clearPostDialListeners() { 354 mPostDialListeners.clear(); 355 } 356 notifyPostDialListeners()357 protected final void notifyPostDialListeners() { 358 if (getPostDialState() == PostDialState.WAIT) { 359 for (PostDialListener listener : new ArrayList<>(mPostDialListeners)) { 360 listener.onPostDialWait(); 361 } 362 } 363 } 364 notifyPostDialListenersNextChar(char c)365 protected final void notifyPostDialListenersNextChar(char c) { 366 for (PostDialListener listener : new ArrayList<>(mPostDialListeners)) { 367 listener.onPostDialChar(c); 368 } 369 } 370 getPostDialState()371 public abstract PostDialState getPostDialState(); 372 373 /** 374 * Returns the portion of the post dial string that has not 375 * yet been dialed, or "" if none 376 */ getRemainingPostDialString()377 public abstract String getRemainingPostDialString(); 378 379 /** 380 * See Phone.setOnPostDialWaitCharacter() 381 */ 382 proceedAfterWaitChar()383 public abstract void proceedAfterWaitChar(); 384 385 /** 386 * See Phone.setOnPostDialWildCharacter() 387 */ proceedAfterWildChar(String str)388 public abstract void proceedAfterWildChar(String str); 389 /** 390 * Cancel any post 391 */ cancelPostDial()392 public abstract void cancelPostDial(); 393 394 /** 395 * Returns the caller id presentation type for incoming and waiting calls 396 * @return one of PRESENTATION_* 397 */ getNumberPresentation()398 public abstract int getNumberPresentation(); 399 400 /** 401 * Returns the User to User Signaling (UUS) information associated with 402 * incoming and waiting calls 403 * @return UUSInfo containing the UUS userdata. 404 */ getUUSInfo()405 public abstract UUSInfo getUUSInfo(); 406 407 /** 408 * Returns the CallFail reason provided by the RIL with the result of 409 * RIL_REQUEST_LAST_CALL_FAIL_CAUSE 410 */ getPreciseDisconnectCause()411 public abstract int getPreciseDisconnectCause(); 412 413 /** 414 * Returns the original Connection instance associated with 415 * this Connection 416 */ getOrigConnection()417 public Connection getOrigConnection() { 418 return mOrigConnection; 419 } 420 421 /** 422 * Returns whether the original ImsPhoneConnection was a member 423 * of a conference call 424 * @return valid only when getOrigConnection() is not null 425 */ isMultiparty()426 public abstract boolean isMultiparty(); 427 migrateFrom(Connection c)428 public void migrateFrom(Connection c) { 429 if (c == null) return; 430 mListeners = c.mListeners; 431 mAddress = c.getAddress(); 432 mNumberPresentation = c.getNumberPresentation(); 433 mDialString = c.getOrigDialString(); 434 mCnapName = c.getCnapName(); 435 mCnapNamePresentation = c.getCnapNamePresentation(); 436 mIsIncoming = c.isIncoming(); 437 mCreateTime = c.getCreateTime(); 438 mConnectTime = c.getConnectTime(); 439 mConnectTimeReal = c.getConnectTimeReal(); 440 mHoldingStartTime = c.getHoldingStartTime(); 441 mOrigConnection = c.getOrigConnection(); 442 } 443 444 /** 445 * Assign a listener to be notified of state changes. 446 * 447 * @param listener A listener. 448 */ addListener(Listener listener)449 public final void addListener(Listener listener) { 450 mListeners.add(listener); 451 } 452 453 /** 454 * Removes a listener. 455 * 456 * @param listener A listener. 457 */ removeListener(Listener listener)458 public final void removeListener(Listener listener) { 459 mListeners.remove(listener); 460 } 461 462 /** 463 * Returns the current video state of the connection. 464 * 465 * @return The video state of the connection. 466 */ getVideoState()467 public int getVideoState() { 468 return mVideoState; 469 } 470 471 /** 472 * Returns the local video capability state for the connection. 473 * 474 * @return {@code True} if the connection has local video capabilities. 475 */ isLocalVideoCapable()476 public boolean isLocalVideoCapable() { 477 return mLocalVideoCapable; 478 } 479 480 /** 481 * Returns the remote video capability state for the connection. 482 * 483 * @return {@code True} if the connection has remote video capabilities. 484 */ isRemoteVideoCapable()485 public boolean isRemoteVideoCapable() { 486 return mRemoteVideoCapable; 487 } 488 489 /** 490 * Returns the {@link android.telecom.Connection.VideoProvider} for the connection. 491 * 492 * @return The {@link android.telecom.Connection.VideoProvider}. 493 */ getVideoProvider()494 public android.telecom.Connection.VideoProvider getVideoProvider() { 495 return mVideoProvider; 496 } 497 498 /** 499 * Returns the audio-quality for the connection. 500 * 501 * @return The audio quality for the connection. 502 */ getAudioQuality()503 public int getAudioQuality() { 504 return mAudioQuality; 505 } 506 507 /** 508 * Sets the videoState for the current connection and reports the changes to all listeners. 509 * Valid video states are defined in {@link android.telecom.VideoProfile}. 510 * 511 * @return The video state. 512 */ setVideoState(int videoState)513 public void setVideoState(int videoState) { 514 mVideoState = videoState; 515 for (Listener l : mListeners) { 516 l.onVideoStateChanged(mVideoState); 517 } 518 } 519 520 /** 521 * Sets whether video capability is present locally. 522 * 523 * @param capable {@code True} if video capable. 524 */ setLocalVideoCapable(boolean capable)525 public void setLocalVideoCapable(boolean capable) { 526 mLocalVideoCapable = capable; 527 for (Listener l : mListeners) { 528 l.onLocalVideoCapabilityChanged(mLocalVideoCapable); 529 } 530 } 531 532 /** 533 * Sets whether video capability is present remotely. 534 * 535 * @param capable {@code True} if video capable. 536 */ setRemoteVideoCapable(boolean capable)537 public void setRemoteVideoCapable(boolean capable) { 538 mRemoteVideoCapable = capable; 539 for (Listener l : mListeners) { 540 l.onRemoteVideoCapabilityChanged(mRemoteVideoCapable); 541 } 542 } 543 544 /** 545 * Set the audio quality for the connection. 546 * 547 * @param audioQuality The audio quality. 548 */ setAudioQuality(int audioQuality)549 public void setAudioQuality(int audioQuality) { 550 mAudioQuality = audioQuality; 551 for (Listener l : mListeners) { 552 l.onAudioQualityChanged(mAudioQuality); 553 } 554 } 555 556 /** 557 * Sets the {@link android.telecom.Connection.VideoProvider} for the connection. 558 * 559 * @param videoProvider The video call provider. 560 */ setVideoProvider(android.telecom.Connection.VideoProvider videoProvider)561 public void setVideoProvider(android.telecom.Connection.VideoProvider videoProvider) { 562 mVideoProvider = videoProvider; 563 for (Listener l : mListeners) { 564 l.onVideoProviderChanged(mVideoProvider); 565 } 566 } 567 setConverted(String oriNumber)568 public void setConverted(String oriNumber) { 569 mNumberConverted = true; 570 mConvertedNumber = mAddress; 571 mAddress = oriNumber; 572 mDialString = oriNumber; 573 } 574 575 /** 576 * Notifies listeners of a change to conference participant(s). 577 * 578 * @param conferenceParticipants The participant(s). 579 */ updateConferenceParticipants(List<ConferenceParticipant> conferenceParticipants)580 public void updateConferenceParticipants(List<ConferenceParticipant> conferenceParticipants) { 581 for (Listener l : mListeners) { 582 l.onConferenceParticipantsChanged(conferenceParticipants); 583 } 584 } 585 586 /** 587 * Notifies this Connection of a request to disconnect a participant of the conference managed 588 * by the connection. 589 * 590 * @param endpoint the {@link Uri} of the participant to disconnect. 591 */ onDisconnectConferenceParticipant(Uri endpoint)592 public void onDisconnectConferenceParticipant(Uri endpoint) { 593 } 594 595 /** 596 * Build a human representation of a connection instance, suitable for debugging. 597 * Don't log personal stuff unless in debug mode. 598 * @return a string representing the internal state of this connection. 599 */ toString()600 public String toString() { 601 StringBuilder str = new StringBuilder(128); 602 603 if (Rlog.isLoggable(LOG_TAG, Log.DEBUG)) { 604 str.append("addr: " + getAddress()) 605 .append(" pres.: " + getNumberPresentation()) 606 .append(" dial: " + getOrigDialString()) 607 .append(" postdial: " + getRemainingPostDialString()) 608 .append(" cnap name: " + getCnapName()) 609 .append("(" + getCnapNamePresentation() + ")"); 610 } 611 str.append(" incoming: " + isIncoming()) 612 .append(" state: " + getState()) 613 .append(" post dial state: " + getPostDialState()); 614 return str.toString(); 615 } 616 } 617