| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License |
| */ |
| |
| package android.telephony.ims; |
| |
| import android.annotation.CallbackExecutor; |
| import android.annotation.NonNull; |
| import android.annotation.SystemApi; |
| import android.os.Message; |
| import android.os.RemoteException; |
| import android.telephony.ims.aidl.IImsCallSessionListener; |
| |
| import java.util.Objects; |
| import java.util.concurrent.Executor; |
| |
| import android.telephony.ims.stub.ImsCallSessionImplBase; |
| import android.util.Log; |
| |
| import com.android.ims.internal.IImsCallSession; |
| import com.android.ims.internal.IImsVideoCallProvider; |
| |
| /** |
| * Provides the call initiation/termination, and media exchange between two IMS endpoints. |
| * It directly communicates with IMS service which implements the IMS protocol behavior. |
| * |
| * @hide |
| */ |
| public class ImsCallSession { |
| private static final String TAG = "ImsCallSession"; |
| |
| /** |
| * Defines IMS call session state. Please use {@link ImsCallSessionImplBase.State} definition. |
| * This is kept around for capability reasons. |
| */ |
| public static class State { |
| public static final int IDLE = 0; |
| public static final int INITIATED = 1; |
| public static final int NEGOTIATING = 2; |
| public static final int ESTABLISHING = 3; |
| public static final int ESTABLISHED = 4; |
| |
| public static final int RENEGOTIATING = 5; |
| public static final int REESTABLISHING = 6; |
| |
| public static final int TERMINATING = 7; |
| public static final int TERMINATED = 8; |
| |
| public static final int INVALID = (-1); |
| |
| /** |
| * Converts the state to string. |
| */ |
| public static String toString(int state) { |
| switch (state) { |
| case IDLE: |
| return "IDLE"; |
| case INITIATED: |
| return "INITIATED"; |
| case NEGOTIATING: |
| return "NEGOTIATING"; |
| case ESTABLISHING: |
| return "ESTABLISHING"; |
| case ESTABLISHED: |
| return "ESTABLISHED"; |
| case RENEGOTIATING: |
| return "RENEGOTIATING"; |
| case REESTABLISHING: |
| return "REESTABLISHING"; |
| case TERMINATING: |
| return "TERMINATING"; |
| case TERMINATED: |
| return "TERMINATED"; |
| default: |
| return "UNKNOWN"; |
| } |
| } |
| |
| private State() { |
| } |
| } |
| |
| /** |
| * Listener for events relating to an IMS session, such as when a session is being |
| * recieved ("on ringing") or a call is outgoing ("on calling"). |
| * <p>Many of these events are also received by {@link ImsCall.Listener}.</p> |
| * @hide |
| */ |
| public static class Listener { |
| /** |
| * Called when a request is sent out to initiate a new session |
| * and 1xx response is received from the network. |
| * |
| * @param session the session object that carries out the IMS session |
| */ |
| public void callSessionProgressing(ImsCallSession session, |
| ImsStreamMediaProfile profile) { |
| // no-op |
| } |
| |
| /** |
| * Called when the session is established. |
| * |
| * @param session the session object that carries out the IMS session |
| */ |
| public void callSessionStarted(ImsCallSession session, |
| ImsCallProfile profile) { |
| // no-op |
| } |
| |
| /** |
| * Called when the session establishment is failed. |
| * |
| * @param session the session object that carries out the IMS session |
| * @param reasonInfo detailed reason of the session establishment failure |
| */ |
| public void callSessionStartFailed(ImsCallSession session, |
| ImsReasonInfo reasonInfo) { |
| } |
| |
| /** |
| * Called when the session is terminated. |
| * |
| * @param session the session object that carries out the IMS session |
| * @param reasonInfo detailed reason of the session termination |
| */ |
| public void callSessionTerminated(ImsCallSession session, |
| ImsReasonInfo reasonInfo) { |
| } |
| |
| /** |
| * Called when the session is in hold. |
| * |
| * @param session the session object that carries out the IMS session |
| */ |
| public void callSessionHeld(ImsCallSession session, |
| ImsCallProfile profile) { |
| } |
| |
| /** |
| * Called when the session hold is failed. |
| * |
| * @param session the session object that carries out the IMS session |
| * @param reasonInfo detailed reason of the session hold failure |
| */ |
| public void callSessionHoldFailed(ImsCallSession session, |
| ImsReasonInfo reasonInfo) { |
| } |
| |
| /** |
| * Called when the session hold is received from the remote user. |
| * |
| * @param session the session object that carries out the IMS session |
| */ |
| public void callSessionHoldReceived(ImsCallSession session, |
| ImsCallProfile profile) { |
| } |
| |
| /** |
| * Called when the session resume is done. |
| * |
| * @param session the session object that carries out the IMS session |
| */ |
| public void callSessionResumed(ImsCallSession session, |
| ImsCallProfile profile) { |
| } |
| |
| /** |
| * Called when the session resume is failed. |
| * |
| * @param session the session object that carries out the IMS session |
| * @param reasonInfo detailed reason of the session resume failure |
| */ |
| public void callSessionResumeFailed(ImsCallSession session, |
| ImsReasonInfo reasonInfo) { |
| } |
| |
| /** |
| * Called when the session resume is received from the remote user. |
| * |
| * @param session the session object that carries out the IMS session |
| */ |
| public void callSessionResumeReceived(ImsCallSession session, |
| ImsCallProfile profile) { |
| } |
| |
| /** |
| * Called when the session merge has been started. At this point, the {@code newSession} |
| * represents the session which has been initiated to the IMS conference server for the |
| * new merged conference. |
| * |
| * @param session the session object that carries out the IMS session |
| * @param newSession the session object that is merged with an active & hold session |
| */ |
| public void callSessionMergeStarted(ImsCallSession session, |
| ImsCallSession newSession, ImsCallProfile profile) { |
| } |
| |
| /** |
| * Called when the session merge is successful and the merged session is active. |
| * |
| * @param session the session object that carries out the IMS session |
| */ |
| public void callSessionMergeComplete(ImsCallSession session) { |
| } |
| |
| /** |
| * Called when the session merge has failed. |
| * |
| * @param session the session object that carries out the IMS session |
| * @param reasonInfo detailed reason of the call merge failure |
| */ |
| public void callSessionMergeFailed(ImsCallSession session, |
| ImsReasonInfo reasonInfo) { |
| } |
| |
| /** |
| * Called when the session is updated (except for hold/unhold). |
| * |
| * @param session the session object that carries out the IMS session |
| */ |
| public void callSessionUpdated(ImsCallSession session, |
| ImsCallProfile profile) { |
| } |
| |
| /** |
| * Called when the session update is failed. |
| * |
| * @param session the session object that carries out the IMS session |
| * @param reasonInfo detailed reason of the session update failure |
| */ |
| public void callSessionUpdateFailed(ImsCallSession session, |
| ImsReasonInfo reasonInfo) { |
| } |
| |
| /** |
| * Called when the session update is received from the remote user. |
| * |
| * @param session the session object that carries out the IMS session |
| */ |
| public void callSessionUpdateReceived(ImsCallSession session, |
| ImsCallProfile profile) { |
| // no-op |
| } |
| |
| /** |
| * Called when the session is extended to the conference session. |
| * |
| * @param session the session object that carries out the IMS session |
| * @param newSession the session object that is extended to the conference |
| * from the active session |
| */ |
| public void callSessionConferenceExtended(ImsCallSession session, |
| ImsCallSession newSession, ImsCallProfile profile) { |
| } |
| |
| /** |
| * Called when the conference extension is failed. |
| * |
| * @param session the session object that carries out the IMS session |
| * @param reasonInfo detailed reason of the conference extension failure |
| */ |
| public void callSessionConferenceExtendFailed(ImsCallSession session, |
| ImsReasonInfo reasonInfo) { |
| } |
| |
| /** |
| * Called when the conference extension is received from the remote user. |
| * |
| * @param session the session object that carries out the IMS session |
| */ |
| public void callSessionConferenceExtendReceived(ImsCallSession session, |
| ImsCallSession newSession, ImsCallProfile profile) { |
| // no-op |
| } |
| |
| /** |
| * Called when the invitation request of the participants is delivered to the conference |
| * server. |
| * |
| * @param session the session object that carries out the IMS session |
| */ |
| public void callSessionInviteParticipantsRequestDelivered(ImsCallSession session) { |
| // no-op |
| } |
| |
| /** |
| * Called when the invitation request of the participants is failed. |
| * |
| * @param session the session object that carries out the IMS session |
| * @param reasonInfo detailed reason of the conference invitation failure |
| */ |
| public void callSessionInviteParticipantsRequestFailed(ImsCallSession session, |
| ImsReasonInfo reasonInfo) { |
| // no-op |
| } |
| |
| /** |
| * Called when the removal request of the participants is delivered to the conference |
| * server. |
| * |
| * @param session the session object that carries out the IMS session |
| */ |
| public void callSessionRemoveParticipantsRequestDelivered(ImsCallSession session) { |
| // no-op |
| } |
| |
| /** |
| * Called when the removal request of the participants is failed. |
| * |
| * @param session the session object that carries out the IMS session |
| * @param reasonInfo detailed reason of the conference removal failure |
| */ |
| public void callSessionRemoveParticipantsRequestFailed(ImsCallSession session, |
| ImsReasonInfo reasonInfo) { |
| // no-op |
| } |
| |
| /** |
| * Called when the conference state is updated. |
| * |
| * @param session the session object that carries out the IMS session |
| */ |
| public void callSessionConferenceStateUpdated(ImsCallSession session, |
| ImsConferenceState state) { |
| // no-op |
| } |
| |
| /** |
| * Called when the USSD message is received from the network. |
| * |
| * @param mode mode of the USSD message (REQUEST / NOTIFY) |
| * @param ussdMessage USSD message |
| */ |
| public void callSessionUssdMessageReceived(ImsCallSession session, |
| int mode, String ussdMessage) { |
| // no-op |
| } |
| |
| /** |
| * Called when an {@link ImsCallSession} may handover from one radio technology to another. |
| * For example, the session may handover from WIFI to LTE if conditions are right. |
| * <p> |
| * If handover is attempted, |
| * {@link #callSessionHandover(ImsCallSession, int, int, ImsReasonInfo)} or |
| * {@link #callSessionHandoverFailed(ImsCallSession, int, int, ImsReasonInfo)} will be |
| * called to indicate the success or failure of the handover. |
| * |
| * @param session IMS session object |
| * @param srcAccessTech original access technology |
| * @param targetAccessTech new access technology |
| */ |
| public void callSessionMayHandover(ImsCallSession session, int srcAccessTech, |
| int targetAccessTech) { |
| // no-op |
| } |
| |
| /** |
| * Called when session access technology changes |
| * |
| * @param session IMS session object |
| * @param srcAccessTech original access technology |
| * @param targetAccessTech new access technology |
| * @param reasonInfo |
| */ |
| public void callSessionHandover(ImsCallSession session, |
| int srcAccessTech, int targetAccessTech, |
| ImsReasonInfo reasonInfo) { |
| // no-op |
| } |
| |
| /** |
| * Called when session access technology change fails |
| * |
| * @param session IMS session object |
| * @param srcAccessTech original access technology |
| * @param targetAccessTech new access technology |
| * @param reasonInfo handover failure reason |
| */ |
| public void callSessionHandoverFailed(ImsCallSession session, |
| int srcAccessTech, int targetAccessTech, |
| ImsReasonInfo reasonInfo) { |
| // no-op |
| } |
| |
| /** |
| * Called when TTY mode of remote party changed |
| * |
| * @param session IMS session object |
| * @param mode TTY mode of remote party |
| */ |
| public void callSessionTtyModeReceived(ImsCallSession session, |
| int mode) { |
| // no-op |
| } |
| |
| /** |
| * Notifies of a change to the multiparty state for this {@code ImsCallSession}. |
| * |
| * @param session The call session. |
| * @param isMultiParty {@code true} if the session became multiparty, {@code false} |
| * otherwise. |
| */ |
| public void callSessionMultipartyStateChanged(ImsCallSession session, |
| boolean isMultiParty) { |
| // no-op |
| } |
| |
| /** |
| * Called when the session supplementary service is received |
| * |
| * @param session the session object that carries out the IMS session |
| */ |
| public void callSessionSuppServiceReceived(ImsCallSession session, |
| ImsSuppServiceNotification suppServiceInfo) { |
| } |
| |
| /** |
| * Received RTT modify request from Remote Party |
| */ |
| public void callSessionRttModifyRequestReceived(ImsCallSession session, |
| ImsCallProfile callProfile) { |
| // no-op |
| } |
| |
| /** |
| * Received response for RTT modify request |
| */ |
| public void callSessionRttModifyResponseReceived(int status) { |
| // no -op |
| } |
| |
| /** |
| * Device received RTT message from Remote UE |
| */ |
| public void callSessionRttMessageReceived(String rttMessage) { |
| // no-op |
| } |
| } |
| |
| private final IImsCallSession miSession; |
| private boolean mClosed = false; |
| private Listener mListener; |
| |
| /** @hide */ |
| public ImsCallSession(IImsCallSession iSession) { |
| miSession = iSession; |
| |
| if (iSession != null) { |
| try { |
| iSession.setListener(new IImsCallSessionListenerProxy()); |
| } catch (RemoteException e) { |
| } |
| } else { |
| mClosed = true; |
| } |
| } |
| |
| /** @hide */ |
| public ImsCallSession(IImsCallSession iSession, Listener listener) { |
| this(iSession); |
| setListener(listener); |
| } |
| |
| /** |
| * Closes this object. This object is not usable after being closed. |
| */ |
| public void close() { |
| synchronized (this) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.close(); |
| mClosed = true; |
| } catch (RemoteException e) { |
| } |
| } |
| } |
| |
| /** |
| * Gets the call ID of the session. |
| * |
| * @return the call ID |
| */ |
| public String getCallId() { |
| if (mClosed) { |
| return null; |
| } |
| |
| try { |
| return miSession.getCallId(); |
| } catch (RemoteException e) { |
| return null; |
| } |
| } |
| |
| /** |
| * Gets the call profile that this session is associated with |
| * |
| * @return the call profile that this session is associated with |
| */ |
| public ImsCallProfile getCallProfile() { |
| if (mClosed) { |
| return null; |
| } |
| |
| try { |
| return miSession.getCallProfile(); |
| } catch (RemoteException e) { |
| return null; |
| } |
| } |
| |
| /** |
| * Gets the local call profile that this session is associated with |
| * |
| * @return the local call profile that this session is associated with |
| */ |
| public ImsCallProfile getLocalCallProfile() { |
| if (mClosed) { |
| return null; |
| } |
| |
| try { |
| return miSession.getLocalCallProfile(); |
| } catch (RemoteException e) { |
| return null; |
| } |
| } |
| |
| /** |
| * Gets the remote call profile that this session is associated with |
| * |
| * @return the remote call profile that this session is associated with |
| */ |
| public ImsCallProfile getRemoteCallProfile() { |
| if (mClosed) { |
| return null; |
| } |
| |
| try { |
| return miSession.getRemoteCallProfile(); |
| } catch (RemoteException e) { |
| return null; |
| } |
| } |
| |
| /** |
| * Gets the video call provider for the session. |
| * |
| * @return The video call provider. |
| * @hide |
| */ |
| public IImsVideoCallProvider getVideoCallProvider() { |
| if (mClosed) { |
| return null; |
| } |
| |
| try { |
| return miSession.getVideoCallProvider(); |
| } catch (RemoteException e) { |
| return null; |
| } |
| } |
| |
| /** |
| * Gets the value associated with the specified property of this session. |
| * |
| * @return the string value associated with the specified property |
| */ |
| public String getProperty(String name) { |
| if (mClosed) { |
| return null; |
| } |
| |
| try { |
| return miSession.getProperty(name); |
| } catch (RemoteException e) { |
| return null; |
| } |
| } |
| |
| /** |
| * Gets the session state. |
| * The value returned must be one of the states in {@link State}. |
| * |
| * @return the session state |
| */ |
| public int getState() { |
| if (mClosed) { |
| return State.INVALID; |
| } |
| |
| try { |
| return miSession.getState(); |
| } catch (RemoteException e) { |
| return State.INVALID; |
| } |
| } |
| |
| /** |
| * Determines if the {@link ImsCallSession} is currently alive (e.g. not in a terminated or |
| * closed state). |
| * |
| * @return {@code True} if the session is alive. |
| */ |
| public boolean isAlive() { |
| if (mClosed) { |
| return false; |
| } |
| |
| int state = getState(); |
| switch (state) { |
| case State.IDLE: |
| case State.INITIATED: |
| case State.NEGOTIATING: |
| case State.ESTABLISHING: |
| case State.ESTABLISHED: |
| case State.RENEGOTIATING: |
| case State.REESTABLISHING: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| /** |
| * Gets the native IMS call session. |
| * @hide |
| */ |
| public IImsCallSession getSession() { |
| return miSession; |
| } |
| |
| /** |
| * Checks if the session is in call. |
| * |
| * @return true if the session is in call |
| */ |
| public boolean isInCall() { |
| if (mClosed) { |
| return false; |
| } |
| |
| try { |
| return miSession.isInCall(); |
| } catch (RemoteException e) { |
| return false; |
| } |
| } |
| |
| /** |
| * Sets the listener to listen to the session events. A {@link ImsCallSession} |
| * can only hold one listener at a time. Subsequent calls to this method |
| * override the previous listener. |
| * |
| * @param listener to listen to the session events of this object |
| * @hide |
| */ |
| public void setListener(Listener listener) { |
| mListener = listener; |
| } |
| |
| /** |
| * Mutes or unmutes the mic for the active call. |
| * |
| * @param muted true if the call is muted, false otherwise |
| */ |
| public void setMute(boolean muted) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.setMute(muted); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Initiates an IMS call with the specified target and call profile. |
| * The session listener is called back upon defined session events. |
| * The method is only valid to call when the session state is in |
| * {@link ImsCallSession.State#IDLE}. |
| * |
| * @param callee dialed string to make the call to |
| * @param profile call profile to make the call with the specified service type, |
| * call type and media information |
| * @see Listener#callSessionStarted, Listener#callSessionStartFailed |
| */ |
| public void start(String callee, ImsCallProfile profile) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.start(callee, profile); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Initiates an IMS conference call with the specified target and call profile. |
| * The session listener is called back upon defined session events. |
| * The method is only valid to call when the session state is in |
| * {@link ImsCallSession.State#IDLE}. |
| * |
| * @param participants participant list to initiate an IMS conference call |
| * @param profile call profile to make the call with the specified service type, |
| * call type and media information |
| * @see Listener#callSessionStarted, Listener#callSessionStartFailed |
| */ |
| public void start(String[] participants, ImsCallProfile profile) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.startConference(participants, profile); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Accepts an incoming call or session update. |
| * |
| * @param callType call type specified in {@link ImsCallProfile} to be answered |
| * @param profile stream media profile {@link ImsStreamMediaProfile} to be answered |
| * @see Listener#callSessionStarted |
| */ |
| public void accept(int callType, ImsStreamMediaProfile profile) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.accept(callType, profile); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Rejects an incoming call or session update. |
| * |
| * @param reason reason code to reject an incoming call |
| * @see Listener#callSessionStartFailed |
| */ |
| public void reject(int reason) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.reject(reason); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Terminates a call. |
| * |
| * @see Listener#callSessionTerminated |
| */ |
| public void terminate(int reason) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.terminate(reason); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Puts a call on hold. When it succeeds, {@link Listener#callSessionHeld} is called. |
| * |
| * @param profile stream media profile {@link ImsStreamMediaProfile} to hold the call |
| * @see Listener#callSessionHeld, Listener#callSessionHoldFailed |
| */ |
| public void hold(ImsStreamMediaProfile profile) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.hold(profile); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Continues a call that's on hold. When it succeeds, |
| * {@link Listener#callSessionResumed} is called. |
| * |
| * @param profile stream media profile {@link ImsStreamMediaProfile} to resume the call |
| * @see Listener#callSessionResumed, Listener#callSessionResumeFailed |
| */ |
| public void resume(ImsStreamMediaProfile profile) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.resume(profile); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Merges the active & hold call. When it succeeds, |
| * {@link Listener#callSessionMergeStarted} is called. |
| * |
| * @see Listener#callSessionMergeStarted , Listener#callSessionMergeFailed |
| */ |
| public void merge() { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.merge(); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Updates the current call's properties (ex. call mode change: video upgrade / downgrade). |
| * |
| * @param callType call type specified in {@link ImsCallProfile} to be updated |
| * @param profile stream media profile {@link ImsStreamMediaProfile} to be updated |
| * @see Listener#callSessionUpdated, Listener#callSessionUpdateFailed |
| */ |
| public void update(int callType, ImsStreamMediaProfile profile) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.update(callType, profile); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Extends this call to the conference call with the specified recipients. |
| * |
| * @param participants list to be invited to the conference call after extending the call |
| * @see Listener#callSessionConferenceExtended |
| * @see Listener#callSessionConferenceExtendFailed |
| */ |
| public void extendToConference(String[] participants) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.extendToConference(participants); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Requests the conference server to invite an additional participants to the conference. |
| * |
| * @param participants list to be invited to the conference call |
| * @see Listener#callSessionInviteParticipantsRequestDelivered |
| * @see Listener#callSessionInviteParticipantsRequestFailed |
| */ |
| public void inviteParticipants(String[] participants) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.inviteParticipants(participants); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Requests the conference server to remove the specified participants from the conference. |
| * |
| * @param participants participant list to be removed from the conference call |
| * @see Listener#callSessionRemoveParticipantsRequestDelivered |
| * @see Listener#callSessionRemoveParticipantsRequestFailed |
| */ |
| public void removeParticipants(String[] participants) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.removeParticipants(participants); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| |
| /** |
| * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>, |
| * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15, |
| * and event flash to 16. Currently, event flash is not supported. |
| * |
| * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs. |
| */ |
| public void sendDtmf(char c, Message result) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.sendDtmf(c, result); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Starts a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>, |
| * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15, |
| * and event flash to 16. Currently, event flash is not supported. |
| * |
| * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs. |
| */ |
| public void startDtmf(char c) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.startDtmf(c); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Stops a DTMF code. |
| */ |
| public void stopDtmf() { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.stopDtmf(); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Sends an USSD message. |
| * |
| * @param ussdMessage USSD message to send |
| */ |
| public void sendUssd(String ussdMessage) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.sendUssd(ussdMessage); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Determines if the session is multiparty. |
| * |
| * @return {@code True} if the session is multiparty. |
| */ |
| public boolean isMultiparty() { |
| if (mClosed) { |
| return false; |
| } |
| |
| try { |
| return miSession.isMultiparty(); |
| } catch (RemoteException e) { |
| return false; |
| } |
| } |
| |
| /** |
| * Sends Rtt Message |
| * |
| * @param rttMessage rtt text to be sent |
| */ |
| public void sendRttMessage(String rttMessage) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.sendRttMessage(rttMessage); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Sends RTT Upgrade request |
| * |
| * @param to : expected profile |
| */ |
| public void sendRttModifyRequest(ImsCallProfile to) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.sendRttModifyRequest(to); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * Sends RTT Upgrade response |
| * |
| * @param response : response for upgrade |
| */ |
| public void sendRttModifyResponse(boolean response) { |
| if (mClosed) { |
| return; |
| } |
| |
| try { |
| miSession.sendRttModifyResponse(response); |
| } catch (RemoteException e) { |
| } |
| } |
| |
| /** |
| * A listener type for receiving notification on IMS call session events. |
| * When an event is generated for an {@link IImsCallSession}, |
| * the application is notified by having one of the methods called on |
| * the {@link IImsCallSessionListener}. |
| */ |
| private class IImsCallSessionListenerProxy extends IImsCallSessionListener.Stub { |
| /** |
| * Notifies the result of the basic session operation (setup / terminate). |
| */ |
| @Override |
| public void callSessionProgressing(ImsStreamMediaProfile profile) { |
| if (mListener != null) { |
| mListener.callSessionProgressing(ImsCallSession.this, profile); |
| } |
| } |
| |
| @Override |
| public void callSessionInitiated(ImsCallProfile profile) { |
| if (mListener != null) { |
| mListener.callSessionStarted(ImsCallSession.this, profile); |
| } |
| } |
| |
| @Override |
| public void callSessionInitiatedFailed(ImsReasonInfo reasonInfo) { |
| if (mListener != null) { |
| mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo); |
| } |
| } |
| |
| @Override |
| public void callSessionTerminated(ImsReasonInfo reasonInfo) { |
| if (mListener != null) { |
| mListener.callSessionTerminated(ImsCallSession.this, reasonInfo); |
| } |
| } |
| |
| /** |
| * Notifies the result of the call hold/resume operation. |
| */ |
| @Override |
| public void callSessionHeld(ImsCallProfile profile) { |
| if (mListener != null) { |
| mListener.callSessionHeld(ImsCallSession.this, profile); |
| } |
| } |
| |
| @Override |
| public void callSessionHoldFailed(ImsReasonInfo reasonInfo) { |
| if (mListener != null) { |
| mListener.callSessionHoldFailed(ImsCallSession.this, reasonInfo); |
| } |
| } |
| |
| @Override |
| public void callSessionHoldReceived(ImsCallProfile profile) { |
| if (mListener != null) { |
| mListener.callSessionHoldReceived(ImsCallSession.this, profile); |
| } |
| } |
| |
| @Override |
| public void callSessionResumed(ImsCallProfile profile) { |
| if (mListener != null) { |
| mListener.callSessionResumed(ImsCallSession.this, profile); |
| } |
| } |
| |
| @Override |
| public void callSessionResumeFailed(ImsReasonInfo reasonInfo) { |
| if (mListener != null) { |
| mListener.callSessionResumeFailed(ImsCallSession.this, reasonInfo); |
| } |
| } |
| |
| @Override |
| public void callSessionResumeReceived(ImsCallProfile profile) { |
| if (mListener != null) { |
| mListener.callSessionResumeReceived(ImsCallSession.this, profile); |
| } |
| } |
| |
| /** |
| * Notifies the start of a call merge operation. |
| * |
| * @param newSession The merged call session. |
| * @param profile The call profile. |
| */ |
| @Override |
| public void callSessionMergeStarted(IImsCallSession newSession, ImsCallProfile profile) { |
| // This callback can be used for future use to add additional |
| // functionality that may be needed between conference start and complete |
| Log.d(TAG, "callSessionMergeStarted"); |
| } |
| |
| /** |
| * Notifies the successful completion of a call merge operation. |
| * |
| * @param newSession The call session. |
| */ |
| @Override |
| public void callSessionMergeComplete(IImsCallSession newSession) { |
| if (mListener != null) { |
| if (newSession != null) { |
| // Check if the active session is the same session that was |
| // active before the merge request was sent. |
| ImsCallSession validActiveSession = ImsCallSession.this; |
| try { |
| if (!Objects.equals(miSession.getCallId(), newSession.getCallId())) { |
| // New session created after conference |
| validActiveSession = new ImsCallSession(newSession); |
| } |
| } catch (RemoteException rex) { |
| Log.e(TAG, "callSessionMergeComplete: exception for getCallId!"); |
| } |
| mListener.callSessionMergeComplete(validActiveSession); |
| } else { |
| // Session already exists. Hence no need to pass |
| mListener.callSessionMergeComplete(null); |
| } |
| } |
| } |
| |
| /** |
| * Notifies of a failure to perform a call merge operation. |
| * |
| * @param reasonInfo The merge failure reason. |
| */ |
| @Override |
| public void callSessionMergeFailed(ImsReasonInfo reasonInfo) { |
| if (mListener != null) { |
| mListener.callSessionMergeFailed(ImsCallSession.this, reasonInfo); |
| } |
| } |
| |
| /** |
| * Notifies the result of call upgrade / downgrade or any other call updates. |
| */ |
| @Override |
| public void callSessionUpdated(ImsCallProfile profile) { |
| if (mListener != null) { |
| mListener.callSessionUpdated(ImsCallSession.this, profile); |
| } |
| } |
| |
| @Override |
| public void callSessionUpdateFailed(ImsReasonInfo reasonInfo) { |
| if (mListener != null) { |
| mListener.callSessionUpdateFailed(ImsCallSession.this, reasonInfo); |
| } |
| } |
| |
| @Override |
| public void callSessionUpdateReceived(ImsCallProfile profile) { |
| if (mListener != null) { |
| mListener.callSessionUpdateReceived(ImsCallSession.this, profile); |
| } |
| } |
| |
| /** |
| * Notifies the result of conference extension. |
| */ |
| @Override |
| public void callSessionConferenceExtended(IImsCallSession newSession, |
| ImsCallProfile profile) { |
| if (mListener != null) { |
| mListener.callSessionConferenceExtended(ImsCallSession.this, |
| new ImsCallSession(newSession), profile); |
| } |
| } |
| |
| @Override |
| public void callSessionConferenceExtendFailed(ImsReasonInfo reasonInfo) { |
| if (mListener != null) { |
| mListener.callSessionConferenceExtendFailed(ImsCallSession.this, reasonInfo); |
| } |
| } |
| |
| @Override |
| public void callSessionConferenceExtendReceived(IImsCallSession newSession, |
| ImsCallProfile profile) { |
| if (mListener != null) { |
| mListener.callSessionConferenceExtendReceived(ImsCallSession.this, |
| new ImsCallSession(newSession), profile); |
| } |
| } |
| |
| /** |
| * Notifies the result of the participant invitation / removal to/from |
| * the conference session. |
| */ |
| @Override |
| public void callSessionInviteParticipantsRequestDelivered() { |
| if (mListener != null) { |
| mListener.callSessionInviteParticipantsRequestDelivered(ImsCallSession.this); |
| } |
| } |
| |
| @Override |
| public void callSessionInviteParticipantsRequestFailed(ImsReasonInfo reasonInfo) { |
| if (mListener != null) { |
| mListener.callSessionInviteParticipantsRequestFailed(ImsCallSession.this, |
| reasonInfo); |
| } |
| } |
| |
| @Override |
| public void callSessionRemoveParticipantsRequestDelivered() { |
| if (mListener != null) { |
| mListener.callSessionRemoveParticipantsRequestDelivered(ImsCallSession.this); |
| } |
| } |
| |
| @Override |
| public void callSessionRemoveParticipantsRequestFailed(ImsReasonInfo reasonInfo) { |
| if (mListener != null) { |
| mListener.callSessionRemoveParticipantsRequestFailed(ImsCallSession.this, |
| reasonInfo); |
| } |
| } |
| |
| /** |
| * Notifies the changes of the conference info. in the conference session. |
| */ |
| @Override |
| public void callSessionConferenceStateUpdated(ImsConferenceState state) { |
| if (mListener != null) { |
| mListener.callSessionConferenceStateUpdated(ImsCallSession.this, state); |
| } |
| } |
| |
| /** |
| * Notifies the incoming USSD message. |
| */ |
| @Override |
| public void callSessionUssdMessageReceived(int mode, String ussdMessage) { |
| if (mListener != null) { |
| mListener.callSessionUssdMessageReceived(ImsCallSession.this, mode, ussdMessage); |
| } |
| } |
| |
| /** |
| * Notifies of a case where a {@link ImsCallSession} may |
| * potentially handover from one radio technology to another. |
| * @param srcAccessTech The source radio access technology; one of the access technology |
| * constants defined in {@link android.telephony.ServiceState}. For |
| * example |
| * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}. |
| * @param targetAccessTech The target radio access technology; one of the access technology |
| * constants defined in {@link android.telephony.ServiceState}. For |
| * example |
| * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}. |
| */ |
| @Override |
| public void callSessionMayHandover(int srcAccessTech, int targetAccessTech) { |
| if (mListener != null) { |
| mListener.callSessionMayHandover(ImsCallSession.this, srcAccessTech, |
| targetAccessTech); |
| } |
| } |
| |
| /** |
| * Notifies of handover information for this call |
| */ |
| @Override |
| public void callSessionHandover(int srcAccessTech, int targetAccessTech, |
| ImsReasonInfo reasonInfo) { |
| if (mListener != null) { |
| mListener.callSessionHandover(ImsCallSession.this, srcAccessTech, |
| targetAccessTech, reasonInfo); |
| } |
| } |
| |
| /** |
| * Notifies of handover failure info for this call |
| */ |
| @Override |
| public void callSessionHandoverFailed(int srcAccessTech, int targetAccessTech, |
| ImsReasonInfo reasonInfo) { |
| if (mListener != null) { |
| mListener.callSessionHandoverFailed(ImsCallSession.this, srcAccessTech, |
| targetAccessTech, reasonInfo); |
| } |
| } |
| |
| /** |
| * Notifies the TTY mode received from remote party. |
| */ |
| @Override |
| public void callSessionTtyModeReceived(int mode) { |
| if (mListener != null) { |
| mListener.callSessionTtyModeReceived(ImsCallSession.this, mode); |
| } |
| } |
| |
| /** |
| * Notifies of a change to the multiparty state for this {@code ImsCallSession}. |
| * |
| * @param isMultiParty {@code true} if the session became multiparty, {@code false} |
| * otherwise. |
| */ |
| public void callSessionMultipartyStateChanged(boolean isMultiParty) { |
| if (mListener != null) { |
| mListener.callSessionMultipartyStateChanged(ImsCallSession.this, isMultiParty); |
| } |
| } |
| |
| @Override |
| public void callSessionSuppServiceReceived(ImsSuppServiceNotification suppServiceInfo ) { |
| if (mListener != null) { |
| mListener.callSessionSuppServiceReceived(ImsCallSession.this, suppServiceInfo); |
| } |
| } |
| |
| /** |
| * Received RTT modify request from remote party |
| */ |
| @Override |
| public void callSessionRttModifyRequestReceived(ImsCallProfile callProfile) { |
| if (mListener != null) { |
| mListener.callSessionRttModifyRequestReceived(ImsCallSession.this, callProfile); |
| } |
| } |
| |
| /** |
| * Received response for RTT modify request |
| */ |
| @Override |
| public void callSessionRttModifyResponseReceived(int status) { |
| if (mListener != null) { |
| mListener.callSessionRttModifyResponseReceived(status); |
| } |
| } |
| |
| /** |
| * RTT Message received |
| */ |
| @Override |
| public void callSessionRttMessageReceived(String rttMessage) { |
| if (mListener != null) { |
| mListener.callSessionRttMessageReceived(rttMessage); |
| } |
| } |
| } |
| |
| /** |
| * Provides a string representation of the {@link ImsCallSession}. Primarily intended for |
| * use in log statements. |
| * |
| * @return String representation of session. |
| */ |
| @Override |
| public String toString() { |
| StringBuilder sb = new StringBuilder(); |
| sb.append("[ImsCallSession objId:"); |
| sb.append(System.identityHashCode(this)); |
| sb.append(" state:"); |
| sb.append(State.toString(getState())); |
| sb.append(" callId:"); |
| sb.append(getCallId()); |
| sb.append("]"); |
| return sb.toString(); |
| } |
| } |