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.Bundle;
21 import android.os.SystemClock;
22 import android.telecom.ConferenceParticipant;
23 import android.telephony.DisconnectCause;
24 import android.telephony.Rlog;
25 import android.util.Log;
26 
27 import java.lang.Override;
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.Set;
31 import java.util.concurrent.CopyOnWriteArraySet;
32 
33 /**
34  * {@hide}
35  */
36 public abstract class Connection {
37 
38     public interface PostDialListener {
onPostDialWait()39         void onPostDialWait();
onPostDialChar(char c)40         void onPostDialChar(char c);
41     }
42 
43     /**
44      * Capabilities that will be mapped to telecom connection
45      * capabilities.
46      */
47     public static class Capability {
48 
49         /**
50          * For an IMS video call, indicates that the local side of the call supports downgrading
51          * from a video call to an audio-only call.
52          */
53         public static final int SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL = 0x00000001;
54 
55         /**
56          * For an IMS video call, indicates that the peer supports downgrading to an audio-only
57          * call.
58          */
59         public static final int SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE = 0x00000002;
60 
61         /**
62          * For an IMS call, indicates that the call supports video locally.
63          */
64         public static final int SUPPORTS_VT_LOCAL_BIDIRECTIONAL = 0x00000004;
65 
66         /**
67          * For an IMS call, indicates that the peer supports video.
68          */
69         public static final int SUPPORTS_VT_REMOTE_BIDIRECTIONAL = 0x00000008;
70 
71         /**
72          * Indicates that the connection is an external connection (e.g. an instance of the class
73          * {@link com.android.internal.telephony.imsphone.ImsExternalConnection}.
74          */
75         public static final int IS_EXTERNAL_CONNECTION = 0x00000010;
76 
77         /**
78          * Indicates that this external connection can be pulled from the remote device to the
79          * local device.
80          */
81         public static final int IS_PULLABLE = 0x00000020;
82     }
83 
84     /**
85      * Listener interface for events related to the connection which should be reported to the
86      * {@link android.telecom.Connection}.
87      */
88     public interface Listener {
onVideoStateChanged(int videoState)89         public void onVideoStateChanged(int videoState);
onConnectionCapabilitiesChanged(int capability)90         public void onConnectionCapabilitiesChanged(int capability);
onWifiChanged(boolean isWifi)91         public void onWifiChanged(boolean isWifi);
onVideoProviderChanged( android.telecom.Connection.VideoProvider videoProvider)92         public void onVideoProviderChanged(
93                 android.telecom.Connection.VideoProvider videoProvider);
onAudioQualityChanged(int audioQuality)94         public void onAudioQualityChanged(int audioQuality);
onConferenceParticipantsChanged(List<ConferenceParticipant> participants)95         public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants);
onCallSubstateChanged(int callSubstate)96         public void onCallSubstateChanged(int callSubstate);
onMultipartyStateChanged(boolean isMultiParty)97         public void onMultipartyStateChanged(boolean isMultiParty);
onConferenceMergedFailed()98         public void onConferenceMergedFailed();
onExtrasChanged(Bundle extras)99         public void onExtrasChanged(Bundle extras);
onExitedEcmMode()100         public void onExitedEcmMode();
onCallPullFailed(Connection externalConnection)101         public void onCallPullFailed(Connection externalConnection);
onHandoverToWifiFailed()102         public void onHandoverToWifiFailed();
onConnectionEvent(String event, Bundle extras)103         public void onConnectionEvent(String event, Bundle extras);
104     }
105 
106     /**
107      * Base listener implementation.
108      */
109     public abstract static class ListenerBase implements Listener {
110         @Override
onVideoStateChanged(int videoState)111         public void onVideoStateChanged(int videoState) {}
112         @Override
onConnectionCapabilitiesChanged(int capability)113         public void onConnectionCapabilitiesChanged(int capability) {}
114         @Override
onWifiChanged(boolean isWifi)115         public void onWifiChanged(boolean isWifi) {}
116         @Override
onVideoProviderChanged( android.telecom.Connection.VideoProvider videoProvider)117         public void onVideoProviderChanged(
118                 android.telecom.Connection.VideoProvider videoProvider) {}
119         @Override
onAudioQualityChanged(int audioQuality)120         public void onAudioQualityChanged(int audioQuality) {}
121         @Override
onConferenceParticipantsChanged(List<ConferenceParticipant> participants)122         public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants) {}
123         @Override
onCallSubstateChanged(int callSubstate)124         public void onCallSubstateChanged(int callSubstate) {}
125         @Override
onMultipartyStateChanged(boolean isMultiParty)126         public void onMultipartyStateChanged(boolean isMultiParty) {}
127         @Override
onConferenceMergedFailed()128         public void onConferenceMergedFailed() {}
129         @Override
onExtrasChanged(Bundle extras)130         public void onExtrasChanged(Bundle extras) {}
131         @Override
onExitedEcmMode()132         public void onExitedEcmMode() {}
133         @Override
onCallPullFailed(Connection externalConnection)134         public void onCallPullFailed(Connection externalConnection) {}
135         @Override
onHandoverToWifiFailed()136         public void onHandoverToWifiFailed() {}
137         @Override
onConnectionEvent(String event, Bundle extras)138         public void onConnectionEvent(String event, Bundle extras) {}
139     }
140 
141     public static final int AUDIO_QUALITY_STANDARD = 1;
142     public static final int AUDIO_QUALITY_HIGH_DEFINITION = 2;
143 
144     /**
145      * The telecom internal call ID associated with this connection.  Only to be used for debugging
146      * purposes.
147      */
148     private String mTelecomCallId;
149 
150     //Caller Name Display
151     protected String mCnapName;
152     protected int mCnapNamePresentation  = PhoneConstants.PRESENTATION_ALLOWED;
153     protected String mAddress;     // MAY BE NULL!!!
154     protected String mDialString;          // outgoing calls only
155     protected int mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED;
156     protected boolean mIsIncoming;
157     /*
158      * These time/timespan values are based on System.currentTimeMillis(),
159      * i.e., "wall clock" time.
160      */
161     protected long mCreateTime;
162     protected long mConnectTime;
163     /*
164      * These time/timespan values are based on SystemClock.elapsedRealTime(),
165      * i.e., time since boot.  They are appropriate for comparison and
166      * calculating deltas.
167      */
168     protected long mConnectTimeReal;
169     protected long mDuration;
170     protected long mHoldingStartTime;  // The time when the Connection last transitioned
171                             // into HOLDING
172     protected Connection mOrigConnection;
173     private List<PostDialListener> mPostDialListeners = new ArrayList<>();
174     public Set<Listener> mListeners = new CopyOnWriteArraySet<>();
175 
176     protected boolean mNumberConverted = false;
177     protected String mConvertedNumber;
178 
179     protected String mPostDialString;      // outgoing calls only
180     protected int mNextPostDialChar;       // index into postDialString
181 
182     protected int mCause = DisconnectCause.NOT_DISCONNECTED;
183     protected PostDialState mPostDialState = PostDialState.NOT_STARTED;
184 
185     private static String LOG_TAG = "Connection";
186 
187     Object mUserData;
188     private int mVideoState;
189     private int mConnectionCapabilities;
190     private boolean mIsWifi;
191     private boolean mAudioModeIsVoip;
192     private int mAudioQuality;
193     private int mCallSubstate;
194     private android.telecom.Connection.VideoProvider mVideoProvider;
195     public Call.State mPreHandoverState = Call.State.IDLE;
196     private Bundle mExtras;
197     private int mPhoneType;
198     private boolean mAnsweringDisconnectsActiveCall;
199     private boolean mAllowAddCallDuringVideoCall;
200 
201     /**
202      * Used to indicate that this originated from pulling a {@link android.telecom.Connection} with
203      * {@link android.telecom.Connection#PROPERTY_IS_EXTERNAL_CALL}.
204      */
205     private boolean mIsPulledCall = false;
206 
207     /**
208      * Where {@link #mIsPulledCall} is {@code true}, contains the dialog Id of the external call
209      * which is being pulled (e.g.
210      * {@link com.android.internal.telephony.imsphone.ImsExternalConnection#getCallId()}).
211      */
212     private int mPulledDialogId;
213 
Connection(int phoneType)214     protected Connection(int phoneType) {
215         mPhoneType = phoneType;
216     }
217 
218     /* Instance Methods */
219 
220     /**
221      * @return The telecom internal call ID associated with this connection.  Only to be used for
222      * debugging purposes.
223      */
getTelecomCallId()224     public String getTelecomCallId() {
225         return mTelecomCallId;
226     }
227 
228     /**
229      * Sets the telecom call ID associated with this connection.
230      *
231      * @param telecomCallId The telecom call ID.
232      */
setTelecomCallId(String telecomCallId)233     public void setTelecomCallId(String telecomCallId) {
234         mTelecomCallId = telecomCallId;
235     }
236 
237     /**
238      * Gets address (e.g. phone number) associated with connection.
239      * TODO: distinguish reasons for unavailability
240      *
241      * @return address or null if unavailable
242      */
243 
getAddress()244     public String getAddress() {
245         return mAddress;
246     }
247 
248     /**
249      * Gets CNAP name associated with connection.
250      * @return cnap name or null if unavailable
251      */
getCnapName()252     public String getCnapName() {
253         return mCnapName;
254     }
255 
256     /**
257      * Get original dial string.
258      * @return original dial string or null if unavailable
259      */
getOrigDialString()260     public String getOrigDialString(){
261         return null;
262     }
263 
264     /**
265      * Gets CNAP presentation associated with connection.
266      * @return cnap name or null if unavailable
267      */
268 
getCnapNamePresentation()269     public int getCnapNamePresentation() {
270        return mCnapNamePresentation;
271     }
272 
273     /**
274      * @return Call that owns this Connection, or null if none
275      */
getCall()276     public abstract Call getCall();
277 
278     /**
279      * Connection create time in currentTimeMillis() format
280      * Basically, set when object is created.
281      * Effectively, when an incoming call starts ringing or an
282      * outgoing call starts dialing
283      */
getCreateTime()284     public long getCreateTime() {
285         return mCreateTime;
286     }
287 
288     /**
289      * Connection connect time in currentTimeMillis() format.
290      * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition.
291      * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition.
292      * Returns 0 before then.
293      */
getConnectTime()294     public long getConnectTime() {
295         return mConnectTime;
296     }
297 
298     /**
299      * Sets the Connection connect time in currentTimeMillis() format.
300      *
301      * @param connectTime the new connect time.
302      */
setConnectTime(long connectTime)303     public void setConnectTime(long connectTime) {
304         mConnectTime = connectTime;
305     }
306 
307     /**
308      * Connection connect time in elapsedRealtime() format.
309      * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition.
310      * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition.
311      * Returns 0 before then.
312      */
getConnectTimeReal()313     public long getConnectTimeReal() {
314         return mConnectTimeReal;
315     }
316 
317     /**
318      * Disconnect time in currentTimeMillis() format.
319      * The time when this Connection makes a transition into ENDED or FAIL.
320      * Returns 0 before then.
321      */
getDisconnectTime()322     public abstract long getDisconnectTime();
323 
324     /**
325      * Returns the number of milliseconds the call has been connected,
326      * or 0 if the call has never connected.
327      * If the call is still connected, then returns the elapsed
328      * time since connect.
329      */
getDurationMillis()330     public long getDurationMillis() {
331         if (mConnectTimeReal == 0) {
332             return 0;
333         } else if (mDuration == 0) {
334             return SystemClock.elapsedRealtime() - mConnectTimeReal;
335         } else {
336             return mDuration;
337         }
338     }
339 
340     /**
341      * The time when this Connection last transitioned into HOLDING
342      * in elapsedRealtime() format.
343      * Returns 0, if it has never made a transition into HOLDING.
344      */
getHoldingStartTime()345     public long getHoldingStartTime() {
346         return mHoldingStartTime;
347     }
348 
349     /**
350      * If this connection is HOLDING, return the number of milliseconds
351      * that it has been on hold for (approximately).
352      * If this connection is in any other state, return 0.
353      */
354 
getHoldDurationMillis()355     public abstract long getHoldDurationMillis();
356 
357     /**
358      * Returns call disconnect cause. Values are defined in
359      * {@link android.telephony.DisconnectCause}. If the call is not yet
360      * disconnected, NOT_DISCONNECTED is returned.
361      */
getDisconnectCause()362     public int getDisconnectCause() {
363         return mCause;
364     }
365 
366     /**
367      * Returns a string disconnect cause which is from vendor.
368      * Vendors may use this string to explain the underline causes of failed calls.
369      * There is no guarantee that it is non-null nor it'll have meaningful stable values.
370      * Only use it when getDisconnectCause() returns a value that is not specific enough, like
371      * ERROR_UNSPECIFIED.
372      */
getVendorDisconnectCause()373     public abstract String getVendorDisconnectCause();
374 
375     /**
376      * Returns true of this connection originated elsewhere
377      * ("MT" or mobile terminated; another party called this terminal)
378      * or false if this call originated here (MO or mobile originated).
379      */
isIncoming()380     public boolean isIncoming() {
381         return mIsIncoming;
382     }
383 
384     /**
385      * If this Connection is connected, then it is associated with
386      * a Call.
387      *
388      * Returns getCall().getState() or Call.State.IDLE if not
389      * connected
390      */
getState()391     public Call.State getState() {
392         Call c;
393 
394         c = getCall();
395 
396         if (c == null) {
397             return Call.State.IDLE;
398         } else {
399             return c.getState();
400         }
401     }
402 
403     /**
404      * If this connection went through handover return the state of the
405      * call that contained this connection before handover.
406      */
getStateBeforeHandover()407     public Call.State getStateBeforeHandover() {
408         return mPreHandoverState;
409    }
410 
411     /**
412      * Get the details of conference participants. Expected to be
413      * overwritten by the Connection subclasses.
414      */
getConferenceParticipants()415     public List<ConferenceParticipant> getConferenceParticipants() {
416         Call c;
417 
418         c = getCall();
419 
420         if (c == null) {
421             return null;
422         } else {
423             return c.getConferenceParticipants();
424         }
425     }
426 
427     /**
428      * isAlive()
429      *
430      * @return true if the connection isn't disconnected
431      * (could be active, holding, ringing, dialing, etc)
432      */
433     public boolean
isAlive()434     isAlive() {
435         return getState().isAlive();
436     }
437 
438     /**
439      * Returns true if Connection is connected and is INCOMING or WAITING
440      */
441     public boolean
isRinging()442     isRinging() {
443         return getState().isRinging();
444     }
445 
446     /**
447      *
448      * @return the userdata set in setUserData()
449      */
getUserData()450     public Object getUserData() {
451         return mUserData;
452     }
453 
454     /**
455      *
456      * @param userdata user can store an any userdata in the Connection object.
457      */
setUserData(Object userdata)458     public void setUserData(Object userdata) {
459         mUserData = userdata;
460     }
461 
462     /**
463      * Hangup individual Connection
464      */
hangup()465     public abstract void hangup() throws CallStateException;
466 
467     /**
468      * Separate this call from its owner Call and assigns it to a new Call
469      * (eg if it is currently part of a Conference call
470      * TODO: Throw exception? Does GSM require error display on failure here?
471      */
separate()472     public abstract void separate() throws CallStateException;
473 
474     public enum PostDialState {
475         NOT_STARTED,    /* The post dial string playback hasn't
476                            been started, or this call is not yet
477                            connected, or this is an incoming call */
478         STARTED,        /* The post dial string playback has begun */
479         WAIT,           /* The post dial string playback is waiting for a
480                            call to proceedAfterWaitChar() */
481         WILD,           /* The post dial string playback is waiting for a
482                            call to proceedAfterWildChar() */
483         COMPLETE,       /* The post dial string playback is complete */
484         CANCELLED,       /* The post dial string playback was cancelled
485                            with cancelPostDial() */
486         PAUSE           /* The post dial string playback is pausing for a
487                            call to processNextPostDialChar*/
488     }
489 
clearUserData()490     public void clearUserData(){
491         mUserData = null;
492     }
493 
addPostDialListener(PostDialListener listener)494     public final void addPostDialListener(PostDialListener listener) {
495         if (!mPostDialListeners.contains(listener)) {
496             mPostDialListeners.add(listener);
497         }
498     }
499 
removePostDialListener(PostDialListener listener)500     public final void removePostDialListener(PostDialListener listener) {
501         mPostDialListeners.remove(listener);
502     }
503 
clearPostDialListeners()504     protected final void clearPostDialListeners() {
505         if (mPostDialListeners != null) {
506             mPostDialListeners.clear();
507         }
508     }
509 
notifyPostDialListeners()510     protected final void notifyPostDialListeners() {
511         if (getPostDialState() == PostDialState.WAIT) {
512             for (PostDialListener listener : new ArrayList<>(mPostDialListeners)) {
513                 listener.onPostDialWait();
514             }
515         }
516     }
517 
notifyPostDialListenersNextChar(char c)518     protected final void notifyPostDialListenersNextChar(char c) {
519         for (PostDialListener listener : new ArrayList<>(mPostDialListeners)) {
520             listener.onPostDialChar(c);
521         }
522     }
523 
getPostDialState()524     public PostDialState getPostDialState() {
525         return mPostDialState;
526     }
527 
528     /**
529      * Returns the portion of the post dial string that has not
530      * yet been dialed, or "" if none
531      */
getRemainingPostDialString()532     public String getRemainingPostDialString() {
533         if (mPostDialState == PostDialState.CANCELLED
534                 || mPostDialState == PostDialState.COMPLETE
535                 || mPostDialString == null
536                 || mPostDialString.length() <= mNextPostDialChar) {
537             return "";
538         }
539 
540         return mPostDialString.substring(mNextPostDialChar);
541     }
542 
543     /**
544      * See Phone.setOnPostDialWaitCharacter()
545      */
546 
proceedAfterWaitChar()547     public abstract void proceedAfterWaitChar();
548 
549     /**
550      * See Phone.setOnPostDialWildCharacter()
551      */
proceedAfterWildChar(String str)552     public abstract void proceedAfterWildChar(String str);
553     /**
554      * Cancel any post
555      */
cancelPostDial()556     public abstract void cancelPostDial();
557 
558     /** Called when the connection has been disconnected */
onDisconnect(int cause)559     public boolean onDisconnect(int cause) {
560         return false;
561     }
562 
563     /**
564      * Returns the caller id presentation type for incoming and waiting calls
565      * @return one of PRESENTATION_*
566      */
getNumberPresentation()567     public abstract int getNumberPresentation();
568 
569     /**
570      * Returns the User to User Signaling (UUS) information associated with
571      * incoming and waiting calls
572      * @return UUSInfo containing the UUS userdata.
573      */
getUUSInfo()574     public abstract UUSInfo getUUSInfo();
575 
576     /**
577      * Returns the CallFail reason provided by the RIL with the result of
578      * RIL_REQUEST_LAST_CALL_FAIL_CAUSE
579      */
getPreciseDisconnectCause()580     public abstract int getPreciseDisconnectCause();
581 
582     /**
583      * Returns the original Connection instance associated with
584      * this Connection
585      */
getOrigConnection()586     public Connection getOrigConnection() {
587         return mOrigConnection;
588     }
589 
590     /**
591      * Returns whether the original ImsPhoneConnection was a member
592      * of a conference call
593      * @return valid only when getOrigConnection() is not null
594      */
isMultiparty()595     public abstract boolean isMultiparty();
596 
597     /**
598      * Applicable only for IMS Call. Determines if this call is the origin of the conference call
599      * (i.e. {@code #isConferenceHost()} is {@code true}), or if it is a member of a conference
600      * hosted on another device.
601      *
602      * @return {@code true} if this call is the origin of the conference call it is a member of,
603      *      {@code false} otherwise.
604      */
isConferenceHost()605     public boolean isConferenceHost() {
606         return false;
607     }
608 
609     /**
610      * Applicable only for IMS Call. Determines if a connection is a member of a conference hosted
611      * on another device.
612      *
613      * @return {@code true} if the connection is a member of a conference hosted on another device.
614      */
isMemberOfPeerConference()615     public boolean isMemberOfPeerConference() {
616         return false;
617     }
618 
migrateFrom(Connection c)619     public void migrateFrom(Connection c) {
620         if (c == null) return;
621         mListeners = c.mListeners;
622         mDialString = c.getOrigDialString();
623         mCreateTime = c.getCreateTime();
624         mConnectTime = c.getConnectTime();
625         mConnectTimeReal = c.getConnectTimeReal();
626         mHoldingStartTime = c.getHoldingStartTime();
627         mOrigConnection = c.getOrigConnection();
628         mPostDialString = c.mPostDialString;
629         mNextPostDialChar = c.mNextPostDialChar;
630     }
631 
632     /**
633      * Assign a listener to be notified of state changes.
634      *
635      * @param listener A listener.
636      */
addListener(Listener listener)637     public final void addListener(Listener listener) {
638         mListeners.add(listener);
639     }
640 
641     /**
642      * Removes a listener.
643      *
644      * @param listener A listener.
645      */
removeListener(Listener listener)646     public final void removeListener(Listener listener) {
647         mListeners.remove(listener);
648     }
649 
650     /**
651      * Returns the current video state of the connection.
652      *
653      * @return The video state of the connection.
654      */
getVideoState()655     public int getVideoState() {
656         return mVideoState;
657     }
658 
659     /**
660      * Called to get Connection capabilities.Returns Capabilities bitmask.
661      * @See Connection.Capability.
662      */
getConnectionCapabilities()663     public int getConnectionCapabilities() {
664         return mConnectionCapabilities;
665     }
666 
667     /**
668      * @return {@code} true if the connection has the specified capabilities.
669      */
hasCapabilities(int connectionCapabilities)670     public boolean hasCapabilities(int connectionCapabilities) {
671         return (mConnectionCapabilities & connectionCapabilities) == connectionCapabilities;
672     }
673 
674     /**
675      * Applies a capability to a capabilities bit-mask.
676      *
677      * @param capabilities The capabilities bit-mask.
678      * @param capability The capability to apply.
679      * @return The capabilities bit-mask with the capability applied.
680      */
addCapability(int capabilities, int capability)681     public static int addCapability(int capabilities, int capability) {
682         return capabilities | capability;
683     }
684 
685     /**
686      * Removes a capability to a capabilities bit-mask.
687      *
688      * @param capabilities The capabilities bit-mask.
689      * @param capability The capability to remove.
690      * @return The capabilities bit-mask with the capability removed.
691      */
removeCapability(int capabilities, int capability)692     public static int removeCapability(int capabilities, int capability) {
693         return capabilities & ~capability;
694     }
695 
696     /**
697      * Returns whether the connection is using a wifi network.
698      *
699      * @return {@code True} if the connection is using a wifi network.
700      */
isWifi()701     public boolean isWifi() {
702         return mIsWifi;
703     }
704 
705     /**
706      * Returns whether the connection uses voip audio mode
707      *
708      * @return {@code True} if the connection uses voip audio mode
709      */
getAudioModeIsVoip()710     public boolean getAudioModeIsVoip() {
711         return mAudioModeIsVoip;
712     }
713 
714     /**
715      * Returns the {@link android.telecom.Connection.VideoProvider} for the connection.
716      *
717      * @return The {@link android.telecom.Connection.VideoProvider}.
718      */
getVideoProvider()719     public android.telecom.Connection.VideoProvider getVideoProvider() {
720         return mVideoProvider;
721     }
722 
723     /**
724      * Returns the audio-quality for the connection.
725      *
726      * @return The audio quality for the connection.
727      */
getAudioQuality()728     public int getAudioQuality() {
729         return mAudioQuality;
730     }
731 
732 
733     /**
734      * Returns the current call substate of the connection.
735      *
736      * @return The call substate of the connection.
737      */
getCallSubstate()738     public int getCallSubstate() {
739         return mCallSubstate;
740     }
741 
742 
743     /**
744      * Sets the videoState for the current connection and reports the changes to all listeners.
745      * Valid video states are defined in {@link android.telecom.VideoProfile}.
746      *
747      * @return The video state.
748      */
setVideoState(int videoState)749     public void setVideoState(int videoState) {
750         mVideoState = videoState;
751         for (Listener l : mListeners) {
752             l.onVideoStateChanged(mVideoState);
753         }
754     }
755 
756     /**
757      * Called to set Connection capabilities.  This will take Capabilities bitmask as input which is
758      * converted from Capabilities constants.
759      *
760      * @See Connection.Capability.
761      * @param capabilities The Capabilities bitmask.
762      */
setConnectionCapabilities(int capabilities)763     public void setConnectionCapabilities(int capabilities) {
764         if (mConnectionCapabilities != capabilities) {
765             mConnectionCapabilities = capabilities;
766             for (Listener l : mListeners) {
767                 l.onConnectionCapabilitiesChanged(mConnectionCapabilities);
768             }
769         }
770     }
771 
772     /**
773      * Sets whether a wifi network is used for the connection.
774      *
775      * @param isWifi {@code True} if wifi is being used.
776      */
setWifi(boolean isWifi)777     public void setWifi(boolean isWifi) {
778         mIsWifi = isWifi;
779         for (Listener l : mListeners) {
780             l.onWifiChanged(mIsWifi);
781         }
782     }
783 
784     /**
785      * Set the voip audio mode for the connection
786      *
787      * @param isVoip {@code True} if voip audio mode is being used.
788      */
setAudioModeIsVoip(boolean isVoip)789     public void setAudioModeIsVoip(boolean isVoip) {
790         mAudioModeIsVoip = isVoip;
791     }
792 
793     /**
794      * Set the audio quality for the connection.
795      *
796      * @param audioQuality The audio quality.
797      */
setAudioQuality(int audioQuality)798     public void setAudioQuality(int audioQuality) {
799         mAudioQuality = audioQuality;
800         for (Listener l : mListeners) {
801             l.onAudioQualityChanged(mAudioQuality);
802         }
803     }
804 
805     /**
806      * Notifies listeners that connection extras has changed.
807      * @param extras New connection extras. This Bundle will be cloned to ensure that any concurrent
808      * modifications to the extras Bundle do not affect Bundle operations in the onExtrasChanged
809      * listeners.
810      */
setConnectionExtras(Bundle extras)811     public void setConnectionExtras(Bundle extras) {
812         if (extras != null) {
813             mExtras = new Bundle(extras);
814         } else {
815             mExtras = null;
816         }
817 
818         for (Listener l : mListeners) {
819             l.onExtrasChanged(mExtras);
820         }
821     }
822 
823     /**
824      * Retrieves the current connection extras.
825      * @return the connection extras.
826      */
getConnectionExtras()827     public Bundle getConnectionExtras() {
828         return mExtras == null ? null : new Bundle(mExtras);
829     }
830 
831     /**
832      * @return {@code true} if answering the call will cause the current active call to be
833      *      disconnected, {@code false} otherwise.
834      */
isActiveCallDisconnectedOnAnswer()835     public boolean isActiveCallDisconnectedOnAnswer() {
836         return mAnsweringDisconnectsActiveCall;
837     }
838 
839     /**
840      * Sets whether answering this call will cause the active call to be disconnected.
841      * <p>
842      * Should only be set {@code true} if there is an active call and this call is ringing.
843      *
844      * @param answeringDisconnectsActiveCall {@code true} if answering the call will call the active
845      *      call to be disconnected.
846      */
setActiveCallDisconnectedOnAnswer(boolean answeringDisconnectsActiveCall)847     public void setActiveCallDisconnectedOnAnswer(boolean answeringDisconnectsActiveCall) {
848         mAnsweringDisconnectsActiveCall = answeringDisconnectsActiveCall;
849     }
850 
shouldAllowAddCallDuringVideoCall()851     public boolean shouldAllowAddCallDuringVideoCall() {
852         return mAllowAddCallDuringVideoCall;
853     }
854 
setAllowAddCallDuringVideoCall(boolean allowAddCallDuringVideoCall)855     public void setAllowAddCallDuringVideoCall(boolean allowAddCallDuringVideoCall) {
856         mAllowAddCallDuringVideoCall = allowAddCallDuringVideoCall;
857     }
858 
859     /**
860      * Sets whether the connection is the result of an external call which was pulled to the local
861      * device.
862      *
863      * @param isPulledCall {@code true} if this connection is the result of pulling an external call
864      *      to the local device.
865      */
setIsPulledCall(boolean isPulledCall)866     public void setIsPulledCall(boolean isPulledCall) {
867         mIsPulledCall = isPulledCall;
868     }
869 
isPulledCall()870     public boolean isPulledCall() {
871         return mIsPulledCall;
872     }
873 
874     /**
875      * For an external call which is being pulled (e.g. {@link #isPulledCall()} is {@code true}),
876      * sets the dialog Id for the external call.  Used to handle failures to pull a call so that the
877      * pulled call can be reconciled with its original external connection.
878      *
879      * @param pulledDialogId The dialog id associated with a pulled call.
880      */
setPulledDialogId(int pulledDialogId)881     public void setPulledDialogId(int pulledDialogId) {
882         mPulledDialogId = pulledDialogId;
883     }
884 
getPulledDialogId()885     public int getPulledDialogId() {
886         return mPulledDialogId;
887     }
888 
889     /**
890      * Sets the call substate for the current connection and reports the changes to all listeners.
891      * Valid call substates are defined in {@link android.telecom.Connection}.
892      *
893      * @return The call substate.
894      */
setCallSubstate(int callSubstate)895     public void setCallSubstate(int callSubstate) {
896         mCallSubstate = callSubstate;
897         for (Listener l : mListeners) {
898             l.onCallSubstateChanged(mCallSubstate);
899         }
900     }
901 
902     /**
903      * Sets the {@link android.telecom.Connection.VideoProvider} for the connection.
904      *
905      * @param videoProvider The video call provider.
906      */
setVideoProvider(android.telecom.Connection.VideoProvider videoProvider)907     public void setVideoProvider(android.telecom.Connection.VideoProvider videoProvider) {
908         mVideoProvider = videoProvider;
909         for (Listener l : mListeners) {
910             l.onVideoProviderChanged(mVideoProvider);
911         }
912     }
913 
setConverted(String oriNumber)914     public void setConverted(String oriNumber) {
915         mNumberConverted = true;
916         mConvertedNumber = mAddress;
917         mAddress = oriNumber;
918         mDialString = oriNumber;
919     }
920 
921     /**
922      * Notifies listeners of a change to conference participant(s).
923      *
924      * @param conferenceParticipants The participant(s).
925      */
updateConferenceParticipants(List<ConferenceParticipant> conferenceParticipants)926     public void updateConferenceParticipants(List<ConferenceParticipant> conferenceParticipants) {
927         for (Listener l : mListeners) {
928             l.onConferenceParticipantsChanged(conferenceParticipants);
929         }
930     }
931 
932     /**
933      * Notifies listeners of a change to the multiparty state of the connection.
934      *
935      * @param isMultiparty The participant(s).
936      */
updateMultipartyState(boolean isMultiparty)937     public void updateMultipartyState(boolean isMultiparty) {
938         for (Listener l : mListeners) {
939             l.onMultipartyStateChanged(isMultiparty);
940         }
941     }
942 
943     /**
944      * Notifies listeners of a failure in merging this connection with the background connection.
945      */
onConferenceMergeFailed()946     public void onConferenceMergeFailed() {
947         for (Listener l : mListeners) {
948             l.onConferenceMergedFailed();
949         }
950     }
951 
952     /**
953      * Notifies that the underlying phone has exited ECM mode.
954      */
onExitedEcmMode()955     public void onExitedEcmMode() {
956         for (Listener l : mListeners) {
957             l.onExitedEcmMode();
958         }
959     }
960 
961     /**
962      * Notifies the connection that a call to {@link #pullExternalCall()} has failed to pull the
963      * call to the local device.
964      *
965      * @param externalConnection The original
966      *      {@link com.android.internal.telephony.imsphone.ImsExternalConnection} from which the
967      *      pull was initiated.
968      */
onCallPullFailed(Connection externalConnection)969     public void onCallPullFailed(Connection externalConnection) {
970         for (Listener l : mListeners) {
971             l.onCallPullFailed(externalConnection);
972         }
973     }
974 
975     /**
976      * Notifies the connection that there was a failure while handing over to WIFI.
977      */
onHandoverToWifiFailed()978     public void onHandoverToWifiFailed() {
979         for (Listener l : mListeners) {
980             l.onHandoverToWifiFailed();
981         }
982     }
983 
984     /**
985      * Notifies the connection of a connection event.
986      */
onConnectionEvent(String event, Bundle extras)987     public void onConnectionEvent(String event, Bundle extras) {
988         for (Listener l : mListeners) {
989             l.onConnectionEvent(event, extras);
990         }
991     }
992 
993     /**
994      * Notifies this Connection of a request to disconnect a participant of the conference managed
995      * by the connection.
996      *
997      * @param endpoint the {@link Uri} of the participant to disconnect.
998      */
onDisconnectConferenceParticipant(Uri endpoint)999     public void onDisconnectConferenceParticipant(Uri endpoint) {
1000     }
1001 
1002     /**
1003      * Called by a {@link android.telecom.Connection} to indicate that this call should be pulled
1004      * to the local device.
1005      */
pullExternalCall()1006     public void pullExternalCall() {
1007     }
1008 
1009     /**
1010      *
1011      */
getPhoneType()1012     public int getPhoneType() {
1013         return mPhoneType;
1014     }
1015 
1016     /**
1017      * Build a human representation of a connection instance, suitable for debugging.
1018      * Don't log personal stuff unless in debug mode.
1019      * @return a string representing the internal state of this connection.
1020      */
toString()1021     public String toString() {
1022         StringBuilder str = new StringBuilder(128);
1023 
1024         str.append(" callId: " + getTelecomCallId());
1025         str.append(" isExternal: " + (((mConnectionCapabilities & Capability.IS_EXTERNAL_CONNECTION)
1026                 == Capability.IS_EXTERNAL_CONNECTION) ? "Y" : "N"));
1027         if (Rlog.isLoggable(LOG_TAG, Log.DEBUG)) {
1028             str.append("addr: " + getAddress())
1029                     .append(" pres.: " + getNumberPresentation())
1030                     .append(" dial: " + getOrigDialString())
1031                     .append(" postdial: " + getRemainingPostDialString())
1032                     .append(" cnap name: " + getCnapName())
1033                     .append("(" + getCnapNamePresentation() + ")");
1034         }
1035         str.append(" incoming: " + isIncoming())
1036                 .append(" state: " + getState())
1037                 .append(" post dial state: " + getPostDialState());
1038         return str.toString();
1039     }
1040 }
1041