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