From 07366813cdf3768dcd69a1f744023747564d654a Mon Sep 17 00:00:00 2001 From: Rekha Kumar Date: Tue, 24 Mar 2015 16:42:31 -0700 Subject: IMS-VT: Upgrade/Downgrade change -Add isVideo API to VideoProfile.VideoState IMS-VT: Fix propagation of device orientation. Orientation received at VT Service is incorrect. Fixed propagation of device orientation to VT service. IMS-VT: Upgrade fix -Add session modify call timed out constant Notify listeners of video quality changed event - Propagate the video quality changed message to the UI. IMS: Add support for video quality - Add Config interface to get/set video quality IMS-VT: Multitasking feature -Support for video multitasking IMS-VT: Modification of data usage aidl Change data usage aidl interface to take parameter type long instead of int Change-Id: I7cda2a689edb86d025dfe8efc8f573918c4bd6bc Propagate the call substate changed message to the UI IMS-VT: Add call modifiable capability PhoneCapababilities call type modifiable constant added IMS-VT: Add a bit mask CALL_SUBSTATE_ALL with all call substate bits set IMS-VT: Enable Video conferencing. Enable Video conferencing. Change-Id: I4240aa6f32c75d6eea8a41da3c87bca651f0901b IMS-VT: Add hide for setVideoProvider API Observed compilation error for SDK generation due to setVideoProvider API. Marking setVideoProvider as hide inorder to resolve the compilation error. IMS-VT: Add persist.radio.ims.audio.output for VT calls -- Add persist.radio.ims.audio.output to set the default speaker for VT calls. -- Add required constants IMS-VT: Add additional error codes for upgrade downgrade -Add support to send additional error codes to UI during upgrade downgrade. Change-Id: Id452d225098fe3bccdcd37d242985c5c761144c1 --- telecomm/java/android/telecom/Call.java | 37 +++++-- telecomm/java/android/telecom/Conference.java | 64 +++++++++++ telecomm/java/android/telecom/Connection.java | 118 ++++++++++++++++++++- .../java/android/telecom/ConnectionService.java | 39 ++++++- .../android/telecom/ConnectionServiceAdapter.java | 22 ++++ .../telecom/ConnectionServiceAdapterServant.java | 11 ++ telecomm/java/android/telecom/InCallService.java | 9 +- telecomm/java/android/telecom/ParcelableCall.java | 18 +++- .../java/android/telecom/ParcelableConference.java | 34 +++++- .../java/android/telecom/ParcelableConnection.java | 14 ++- .../java/android/telecom/RemoteConnection.java | 44 +++++++- .../android/telecom/RemoteConnectionService.java | 7 ++ telecomm/java/android/telecom/VideoCallImpl.java | 15 ++- .../java/android/telecom/VideoCallbackServant.java | 16 ++- telecomm/java/android/telecom/VideoProfile.java | 16 +++ .../telecom/IConnectionServiceAdapter.aidl | 2 + .../android/internal/telecom/IVideoCallback.aidl | 4 +- telephony/java/com/android/ims/ImsCallProfile.java | 38 +++++-- .../java/com/android/ims/ImsConfigListener.aidl | 24 ++++- .../com/android/ims/internal/IImsCallSession.aidl | 7 ++ .../java/com/android/ims/internal/IImsConfig.aidl | 20 ++++ .../ims/internal/IImsVideoCallCallback.aidl | 4 +- .../android/internal/telephony/PhoneConstants.java | 7 ++ .../internal/telephony/TelephonyProperties.java | 8 ++ 24 files changed, 532 insertions(+), 46 deletions(-) diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index 436f20a..2d2c246 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -208,10 +208,6 @@ public final class Call { */ public static final int CAPABILITY_WIFI = 0x00010000; - //****************************************************************************************** - // Next CAPABILITY value: 0x00020000 - //****************************************************************************************** - /** * Indicates that the current device callback number should be shown. * @@ -225,8 +221,14 @@ public final class Call { */ public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000; + /** + * Call type can be modified for IMS call + * @hide + */ + public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000; + //****************************************************************************************** - // Next CAPABILITY value: 0x00080000 + // Next CAPABILITY value: 0x00100000 //****************************************************************************************** private final Uri mHandle; @@ -242,6 +244,7 @@ public final class Call { private final int mVideoState; private final StatusHints mStatusHints; private final Bundle mExtras; + private final int mCallSubstate; /** * Whether the supplied capabilities supports the specified capability. @@ -329,6 +332,9 @@ public final class Call { if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) { builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO"); } + if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) { + builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO"); + } builder.append("]"); return builder.toString(); } @@ -434,6 +440,14 @@ public final class Call { return mExtras; } + /** + * @return The substate of the {@code Call}. + * @hide + */ + public int getCallSubstate() { + return mCallSubstate; + } + @Override public boolean equals(Object o) { if (o instanceof Details) { @@ -452,7 +466,8 @@ public final class Call { Objects.equals(mGatewayInfo, d.mGatewayInfo) && Objects.equals(mVideoState, d.mVideoState) && Objects.equals(mStatusHints, d.mStatusHints) && - Objects.equals(mExtras, d.mExtras); + Objects.equals(mExtras, d.mExtras) && + Objects.equals(mCallSubstate, d.mCallSubstate); } return false; } @@ -472,7 +487,8 @@ public final class Call { Objects.hashCode(mGatewayInfo) + Objects.hashCode(mVideoState) + Objects.hashCode(mStatusHints) + - Objects.hashCode(mExtras); + Objects.hashCode(mExtras) + + Objects.hashCode(mCallSubstate); } /** {@hide} */ @@ -489,7 +505,8 @@ public final class Call { GatewayInfo gatewayInfo, int videoState, StatusHints statusHints, - Bundle extras) { + Bundle extras, + int callSubstate) { mHandle = handle; mHandlePresentation = handlePresentation; mCallerDisplayName = callerDisplayName; @@ -503,6 +520,7 @@ public final class Call { mVideoState = videoState; mStatusHints = statusHints; mExtras = extras; + mCallSubstate = callSubstate; } } @@ -883,7 +901,8 @@ public final class Call { parcelableCall.getGatewayInfo(), parcelableCall.getVideoState(), parcelableCall.getStatusHints(), - parcelableCall.getExtras()); + parcelableCall.getExtras(), + parcelableCall.getCallSubstate()); boolean detailsChanged = !Objects.equals(mDetails, details); if (detailsChanged) { mDetails = details; diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index 33bbb29..ddaedcd 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -17,10 +17,12 @@ package android.telecom; import android.annotation.SystemApi; +import android.telecom.Connection.VideoProvider; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; @@ -49,6 +51,8 @@ public abstract class Conference implements IConferenceable { public void onDestroyed(Conference conference) {} public void onConnectionCapabilitiesChanged( Conference conference, int connectionCapabilities) {} + public void onVideoStateChanged(Conference c, int videoState) { } + public void onVideoProviderChanged(Conference c, Connection.VideoProvider videoProvider) {} } private final Set mListeners = new CopyOnWriteArraySet<>(); @@ -180,6 +184,22 @@ public abstract class Conference implements IConferenceable { } /** + * Returns VideoProvider of the primary call. This can be null. + * @hide + */ + public VideoProvider getVideoProvider() { + return null; + } + + /** + * Returns video state of the primary call. + * @hide + */ + public int getVideoState() { + return VideoProfile.VideoState.AUDIO_ONLY; + } + + /** * Invoked when the Conference and all it's {@link Connection}s should be disconnected. */ public void onDisconnect() {} @@ -309,6 +329,7 @@ public abstract class Conference implements IConferenceable { * @return True if the connection was successfully added. */ public final boolean addConnection(Connection connection) { + Log.d(this, "Connection=%s, connection=", connection); if (connection != null && !mChildConnections.contains(connection)) { if (connection.setConference(this)) { mChildConnections.add(connection); @@ -355,6 +376,38 @@ public abstract class Conference implements IConferenceable { fireOnConferenceableConnectionsChanged(); } + /** + * Set the video state for the conference. + * Valid values: {@link VideoProfile.VideoState#AUDIO_ONLY}, + * {@link VideoProfile.VideoState#BIDIRECTIONAL}, + * {@link VideoProfile.VideoState#TX_ENABLED}, + * {@link VideoProfile.VideoState#RX_ENABLED}. + * + * @param videoState The new video state. + * @hide + */ + public final void setVideoState(Connection c, int videoState) { + Log.d(this, "setVideoState Conference: %s Connection: %s VideoState: %s", + this, c, videoState); + for (Listener l : mListeners) { + l.onVideoStateChanged(this, videoState); + } + } + + /** + * Sets the video connection provider. + * + * @param videoProvider The video provider. + * @hide + */ + public final void setVideoProvider(Connection c, Connection.VideoProvider videoProvider) { + Log.d(this, "setVideoProvider Conference: %s Connection: %s VideoState: %s", + this, c, videoProvider); + for (Listener l : mListeners) { + l.onVideoProviderChanged(this, videoProvider); + } + } + private final void fireOnConferenceableConnectionsChanged() { for (Listener l : mListeners) { l.onConferenceableConnectionsChanged(this, getConferenceableConnections()); @@ -484,4 +537,15 @@ public abstract class Conference implements IConferenceable { } mConferenceableConnections.clear(); } + + @Override + public String toString() { + return String.format(Locale.US, + "[State: %s,Capabilites: %s, VideoState: %s, VideoProvider: %s, ThisObject %s]", + Connection.stateToString(mState), + Call.Details.capabilitiesToString(mConnectionCapabilities), + getVideoState(), + getVideoProvider(), + super.toString()); + } } diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index bab064e..c34b080 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -186,10 +186,58 @@ public abstract class Connection implements IConferenceable { */ public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000; + /** + * Call type can be modified for IMS call + * @hide + */ + public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000; + //********************************************************************************************** - // Next CAPABILITY value: 0x00080000 + // Next CAPABILITY value: 0x00100000 //********************************************************************************************** + /** + * Call substate bitmask values + */ + + /* Default case */ + /** + * @hide + */ + public static final int SUBSTATE_NONE = 0; + + /* Indicates that the call is connected but audio attribute is suspended */ + /** + * @hide + */ + public static final int SUBSTATE_AUDIO_CONNECTED_SUSPENDED = 0x1; + + /* Indicates that the call is connected but video attribute is suspended */ + /** + * @hide + */ + public static final int SUBSTATE_VIDEO_CONNECTED_SUSPENDED = 0x2; + + /* Indicates that the call is established but media retry is needed */ + /** + * @hide + */ + public static final int SUBSTATE_AVP_RETRY = 0x4; + + /* Indicates that the call is multitasking */ + /** + * @hide + */ + public static final int SUBSTATE_MEDIA_PAUSED = 0x8; + + /* Mask containing all the call substate bits set */ + /** + * @hide + */ + public static final int SUBSTATE_ALL = SUBSTATE_AUDIO_CONNECTED_SUSPENDED | + SUBSTATE_VIDEO_CONNECTED_SUSPENDED | SUBSTATE_AVP_RETRY | + SUBSTATE_MEDIA_PAUSED; + // Flag controlling whether PII is emitted into the logs private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG); @@ -294,6 +342,9 @@ public abstract class Connection implements IConferenceable { if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) { builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO"); } + if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) { + builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO"); + } builder.append("]"); return builder.toString(); } @@ -322,6 +373,7 @@ public abstract class Connection implements IConferenceable { public void onConferenceParticipantsChanged(Connection c, List participants) {} public void onConferenceStarted() {} + public void onCallSubstateChanged(Connection c, int substate) {} } /** @hide */ @@ -377,6 +429,16 @@ public abstract class Connection implements IConferenceable { */ public static final int SESSION_MODIFY_REQUEST_INVALID = 3; + /** + * Session modify request timed out. + */ + public static final int SESSION_MODIFY_REQUEST_TIMED_OUT = 4; + + /** + * Session modify request rejected by remote UE. + */ + public static final int SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE = 5; + private static final int MSG_SET_VIDEO_CALLBACK = 1; private static final int MSG_SET_CAMERA = 2; private static final int MSG_SET_PREVIEW_SURFACE = 3; @@ -462,7 +524,8 @@ public abstract class Connection implements IConferenceable { } public void setDeviceOrientation(int rotation) { - mMessageHandler.obtainMessage(MSG_SET_DEVICE_ORIENTATION, rotation).sendToTarget(); + mMessageHandler.obtainMessage( + MSG_SET_DEVICE_ORIENTATION, rotation, 0).sendToTarget(); } public void setZoom(float value) { @@ -656,7 +719,7 @@ public abstract class Connection implements IConferenceable { * * @param dataUsage The updated data usage. */ - public void changeCallDataUsage(int dataUsage) { + public void changeCallDataUsage(long dataUsage) { if (mVideoCallback != null) { try { mVideoCallback.changeCallDataUsage(dataUsage); @@ -678,6 +741,20 @@ public abstract class Connection implements IConferenceable { } } } + + /** + * Invokes callback method defined in In-Call UI. + * + * @param videoQuality The updated video quality. + */ + public void changeVideoQuality(int videoQuality) { + if (mVideoCallback != null) { + try { + mVideoCallback.changeVideoQuality(videoQuality); + } catch (RemoteException ignored) { + } + } + } } private final Listener mConnectionDeathListener = new Listener() { @@ -724,6 +801,7 @@ public abstract class Connection implements IConferenceable { private DisconnectCause mDisconnectCause; private Conference mConference; private ConnectionService mConnectionService; + private int mCallSubstate; /** * Create a new Connection. @@ -782,6 +860,21 @@ public abstract class Connection implements IConferenceable { } /** + * Returns the call substate of the call. + * Valid values: {@link Connection#SUBSTATE_NONE}, + * {@link Connection#SUBSTATE_AUDIO_CONNECTED_SUSPENDED}, + * {@link Connection#SUBSTATE_VIDEO_CONNECTED_SUSPENDED}, + * {@link Connection#SUBSTATE_AVP_RETRY}, + * {@link Connection#SUBSTATE_MEDIA_PAUSED}. + * + * @param callSubstate The new call substate. + * @hide + */ + public final int getCallSubstate() { + return mCallSubstate; + } + + /** * @return The audio state of the connection, describing how its audio is currently * being routed by the system. This is {@code null} if this Connection * does not directly know about its audio state. @@ -960,6 +1053,25 @@ public abstract class Connection implements IConferenceable { } /** + * Set the call substate for the connection. + * Valid values: {@link Connection#SUBSTATE_NONE}, + * {@link Connection#SUBSTATE_AUDIO_CONNECTED_SUSPENDED}, + * {@link Connection#SUBSTATE_VIDEO_CONNECTED_SUSPENDED}, + * {@link Connection#SUBSTATE_AVP_RETRY}, + * {@link Connection#SUBSTATE_MEDIA_PAUSED}. + * + * @param callSubstate The new call substate. + * @hide + */ + public final void setCallSubstate(int callSubstate) { + Log.d(this, "setCallSubstate %d", callSubstate); + mCallSubstate = callSubstate; + for (Listener l : mListeners) { + l.onCallSubstateChanged(this, mCallSubstate); + } + } + + /** * Sets state to active (e.g., an ongoing connection where two or more parties can actively * communicate). */ diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index dfdc3e1..0c719cd 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -415,6 +415,21 @@ public abstract class ConnectionService extends Service { Connection.capabilitiesToString(connectionCapabilities)); mAdapter.setConnectionCapabilities(id, connectionCapabilities); } + + @Override + public void onVideoStateChanged(Conference c, int videoState) { + String id = mIdByConference.get(c); + Log.d(this, "onVideoStateChanged set video state %d", videoState); + mAdapter.setVideoState(id, videoState); + } + + @Override + public void onVideoProviderChanged(Conference c, Connection.VideoProvider videoProvider) { + String id = mIdByConference.get(c); + Log.d(this, "onVideoProviderChanged: Connection: %s, VideoProvider: %s", c, + videoProvider); + mAdapter.setVideoProvider(id, videoProvider); + } }; private final Connection.Listener mConnectionListener = new Connection.Listener() { @@ -508,6 +523,8 @@ public abstract class ConnectionService extends Service { @Override public void onVideoProviderChanged(Connection c, Connection.VideoProvider videoProvider) { String id = mIdByConnection.get(c); + Log.d(this, "onVideoProviderChanged: Connection: %s, VideoProvider: %s", c, + videoProvider); mAdapter.setVideoProvider(id, videoProvider); } @@ -542,6 +559,13 @@ public abstract class ConnectionService extends Service { mAdapter.setIsConferenced(id, conferenceId); } } + + @Override + public void onCallSubstateChanged(Connection c, int callSubstate) { + String id = mIdByConnection.get(c); + Log.d(this, "Adapter set call substate %d", callSubstate); + mAdapter.setCallSubstate(id, callSubstate); + } }; /** {@inheritDoc} */ @@ -611,7 +635,8 @@ public abstract class ConnectionService extends Service { connection.getAudioModeIsVoip(), connection.getStatusHints(), connection.getDisconnectCause(), - createIdList(connection.getConferenceables()))); + createIdList(connection.getConferenceables()), + connection.getCallSubstate())); } private void abort(String callId) { @@ -871,6 +896,8 @@ public abstract class ConnectionService extends Service { * @param conference The new conference object. */ public final void addConference(Conference conference) { + Log.d(this, "addConference: conference=%s", conference); + String id = addConferenceInternal(conference); if (id != null) { List connectionIds = new ArrayList<>(2); @@ -884,8 +911,14 @@ public abstract class ConnectionService extends Service { conference.getState(), conference.getConnectionCapabilities(), connectionIds, - conference.getConnectTimeMillis()); + conference.getVideoProvider() == null ? + null : conference.getVideoProvider().getInterface(), + conference.getVideoState(), + conference.getConnectTimeMillis() + ); mAdapter.addConferenceCall(id, parcelableConference); + mAdapter.setVideoProvider(id, conference.getVideoProvider()); + mAdapter.setVideoState(id, conference.getVideoState()); // Go through any child calls and set the parent. for (Connection connection : conference.getConnections()) { @@ -926,7 +959,7 @@ public abstract class ConnectionService extends Service { connection.getAudioModeIsVoip(), connection.getStatusHints(), connection.getDisconnectCause(), - emptyList); + emptyList, connection.getCallSubstate()); mAdapter.addExistingConnection(id, parcelableConnection); } } diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java index d026a28..a410976 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java @@ -369,4 +369,26 @@ final class ConnectionServiceAdapter implements DeathRecipient { } } } + + /** + * Set the call substate for the connection. + * Valid values: {@link Connection#CALL_SUBSTATE_NONE}, + * {@link Connection#CALL_SUBSTATE_AUDIO_CONNECTED_SUSPENDED}, + * {@link Connection#CALL_SUBSTATE_VIDEO_CONNECTED_SUSPENDED}, + * {@link Connection#CALL_SUBSTATE_AVP_RETRY}, + * {@link Connection#CALL_SUBSTATE_MEDIA_PAUSED}. + * + * @param callId The unique ID of the call to set the substate for. + * @param callSubstate The new call substate. + * @hide + */ + public final void setCallSubstate(String callId, int callSubstate) { + Log.v(this, "setCallSubstate: %d", callSubstate); + for (IConnectionServiceAdapter adapter : mAdapters) { + try { + adapter.setCallSubstate(callId, callSubstate); + } catch (RemoteException ignored) { + } + } + } } diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java index 429f296..5f93789 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java @@ -59,6 +59,7 @@ final class ConnectionServiceAdapterServant { private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 20; private static final int MSG_ADD_EXISTING_CONNECTION = 21; private static final int MSG_ON_POST_DIAL_CHAR = 22; + private static final int MSG_SET_CALL_SUBSTATE = 23; private final IConnectionServiceAdapter mDelegate; @@ -220,6 +221,10 @@ final class ConnectionServiceAdapterServant { } break; } + case MSG_SET_CALL_SUBSTATE: { + mDelegate.setCallSubstate((String) msg.obj, msg.arg1); + break; + } } } }; @@ -384,6 +389,12 @@ final class ConnectionServiceAdapterServant { args.arg2 = connection; mHandler.obtainMessage(MSG_ADD_EXISTING_CONNECTION, args).sendToTarget(); } + + @Override + public void setCallSubstate(String connectionId, int callSubstate) { + mHandler.obtainMessage(MSG_SET_CALL_SUBSTATE, callSubstate, 0, + connectionId).sendToTarget(); + } }; public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) { diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java index a85e84d..c0c59fa 100644 --- a/telecomm/java/android/telecom/InCallService.java +++ b/telecomm/java/android/telecom/InCallService.java @@ -361,11 +361,18 @@ public abstract class InCallService extends Service { public abstract void onPeerDimensionsChanged(int width, int height); /** + * Handles a change to the video quality. + * + * @param videoQuality The updated peer video quality. + */ + public abstract void onVideoQualityChanged(int videoQuality); + + /** * Handles an update to the total data used for the current session. * * @param dataUsage The updated data usage. */ - public abstract void onCallDataUsageChanged(int dataUsage); + public abstract void onCallDataUsageChanged(long dataUsage); /** * Handles a change in camera capabilities. diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java index c5c3d11..adc648f 100644 --- a/telecomm/java/android/telecom/ParcelableCall.java +++ b/telecomm/java/android/telecom/ParcelableCall.java @@ -54,6 +54,7 @@ public final class ParcelableCall implements Parcelable { private final int mVideoState; private final List mConferenceableCallIds; private final Bundle mExtras; + private int mCallSubstate; public ParcelableCall( String id, @@ -75,7 +76,8 @@ public final class ParcelableCall implements Parcelable { StatusHints statusHints, int videoState, List conferenceableCallIds, - Bundle extras) { + Bundle extras, + int callSubstate) { mId = id; mState = state; mDisconnectCause = disconnectCause; @@ -96,6 +98,7 @@ public final class ParcelableCall implements Parcelable { mVideoState = videoState; mConferenceableCallIds = Collections.unmodifiableList(conferenceableCallIds); mExtras = extras; + mCallSubstate = callSubstate; } /** The unique ID of the call. */ @@ -232,6 +235,14 @@ public final class ParcelableCall implements Parcelable { return mExtras; } + /** + * The call substate. + * @return The substate of the call. + */ + public int getCallSubstate() { + return mCallSubstate; + } + /** Responsible for creating ParcelableCall objects for deserialized Parcels. */ public static final Parcelable.Creator CREATOR = new Parcelable.Creator () { @@ -262,6 +273,7 @@ public final class ParcelableCall implements Parcelable { List conferenceableCallIds = new ArrayList<>(); source.readList(conferenceableCallIds, classLoader); Bundle extras = source.readParcelable(classLoader); + int callSubstate = source.readInt(); return new ParcelableCall( id, state, @@ -282,7 +294,8 @@ public final class ParcelableCall implements Parcelable { statusHints, videoState, conferenceableCallIds, - extras); + extras, + callSubstate); } @Override @@ -321,6 +334,7 @@ public final class ParcelableCall implements Parcelable { destination.writeInt(mVideoState); destination.writeList(mConferenceableCallIds); destination.writeParcelable(mExtras, 0); + destination.writeInt(mCallSubstate); } @Override diff --git a/telecomm/java/android/telecom/ParcelableConference.java b/telecomm/java/android/telecom/ParcelableConference.java index dcc2713..ab82549 100644 --- a/telecomm/java/android/telecom/ParcelableConference.java +++ b/telecomm/java/android/telecom/ParcelableConference.java @@ -22,6 +22,8 @@ import android.os.Parcelable; import java.util.ArrayList; import java.util.List; +import com.android.internal.telecom.IVideoProvider; + /** * A parcelable representation of a conference connection. * @hide @@ -33,17 +35,23 @@ public final class ParcelableConference implements Parcelable { private int mConnectionCapabilities; private List mConnectionIds; private long mConnectTimeMillis; + private final IVideoProvider mVideoProvider; + private final int mVideoState; public ParcelableConference( PhoneAccountHandle phoneAccount, int state, int connectionCapabilities, - List connectionIds) { + List connectionIds, + IVideoProvider videoProvider, + int videoState) { mPhoneAccount = phoneAccount; mState = state; mConnectionCapabilities = connectionCapabilities; mConnectionIds = connectionIds; mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED; + mVideoProvider = videoProvider; + mVideoState = videoState; } public ParcelableConference( @@ -51,8 +59,10 @@ public final class ParcelableConference implements Parcelable { int state, int connectionCapabilities, List connectionIds, + IVideoProvider videoProvider, + int videoState, long connectTimeMillis) { - this(phoneAccount, state, connectionCapabilities, connectionIds); + this(phoneAccount, state, connectionCapabilities, connectionIds, videoProvider, videoState); mConnectTimeMillis = connectTimeMillis; } @@ -69,6 +79,10 @@ public final class ParcelableConference implements Parcelable { .append(mConnectTimeMillis) .append(", children: ") .append(mConnectionIds) + .append(", VideoState: ") + .append(mVideoState) + .append(", VideoProvider: ") + .append(mVideoProvider) .toString(); } @@ -91,6 +105,13 @@ public final class ParcelableConference implements Parcelable { public long getConnectTimeMillis() { return mConnectTimeMillis; } + public IVideoProvider getVideoProvider() { + return mVideoProvider; + } + + public int getVideoState() { + return mVideoState; + } public static final Parcelable.Creator CREATOR = new Parcelable.Creator () { @@ -104,8 +125,12 @@ public final class ParcelableConference implements Parcelable { source.readList(connectionIds, classLoader); long connectTimeMillis = source.readLong(); + IVideoProvider videoCallProvider = + IVideoProvider.Stub.asInterface(source.readStrongBinder()); + int videoState = source.readInt(); + return new ParcelableConference(phoneAccount, state, capabilities, connectionIds, - connectTimeMillis); + videoCallProvider, videoState); } @Override @@ -128,5 +153,8 @@ public final class ParcelableConference implements Parcelable { destination.writeInt(mConnectionCapabilities); destination.writeList(mConnectionIds); destination.writeLong(mConnectTimeMillis); + destination.writeStrongBinder( + mVideoProvider != null ? mVideoProvider.asBinder() : null); + destination.writeInt(mVideoState); } } diff --git a/telecomm/java/android/telecom/ParcelableConnection.java b/telecomm/java/android/telecom/ParcelableConnection.java index 552e250..b60b99d 100644 --- a/telecomm/java/android/telecom/ParcelableConnection.java +++ b/telecomm/java/android/telecom/ParcelableConnection.java @@ -46,6 +46,7 @@ public final class ParcelableConnection implements Parcelable { private final StatusHints mStatusHints; private final DisconnectCause mDisconnectCause; private final List mConferenceableConnectionIds; + private final int mCallSubstate; /** @hide */ public ParcelableConnection( @@ -62,7 +63,8 @@ public final class ParcelableConnection implements Parcelable { boolean isVoipAudioMode, StatusHints statusHints, DisconnectCause disconnectCause, - List conferenceableConnectionIds) { + List conferenceableConnectionIds, + int callSubstate) { mPhoneAccount = phoneAccount; mState = state; mConnectionCapabilities = capabilities; @@ -77,6 +79,7 @@ public final class ParcelableConnection implements Parcelable { mStatusHints = statusHints; mDisconnectCause = disconnectCause; this.mConferenceableConnectionIds = conferenceableConnectionIds; + mCallSubstate = callSubstate; } public PhoneAccountHandle getPhoneAccount() { @@ -136,6 +139,10 @@ public final class ParcelableConnection implements Parcelable { return mConferenceableConnectionIds; } + public int getCallSubstate() { + return mCallSubstate; + } + @Override public String toString() { return new StringBuilder() @@ -170,6 +177,7 @@ public final class ParcelableConnection implements Parcelable { DisconnectCause disconnectCause = source.readParcelable(classLoader); List conferenceableConnectionIds = new ArrayList<>(); source.readStringList(conferenceableConnectionIds); + int callSubstate = source.readInt(); return new ParcelableConnection( phoneAccount, @@ -185,7 +193,8 @@ public final class ParcelableConnection implements Parcelable { audioModeIsVoip, statusHints, disconnectCause, - conferenceableConnectionIds); + conferenceableConnectionIds, + callSubstate); } @Override @@ -218,5 +227,6 @@ public final class ParcelableConnection implements Parcelable { destination.writeParcelable(mStatusHints, 0); destination.writeParcelable(mDisconnectCause, 0); destination.writeStringList(mConferenceableConnectionIds); + destination.writeInt(mCallSubstate); } } diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java index 486691f..be7a0a0 100644 --- a/telecomm/java/android/telecom/RemoteConnection.java +++ b/telecomm/java/android/telecom/RemoteConnection.java @@ -161,6 +161,16 @@ public final class RemoteConnection { public void onVideoStateChanged(RemoteConnection connection, int videoState) {} /** + * Indicates that the call substate of this {@code RemoteConnection} has changed. + * See {@link #getCallSubstate()}. + * + * @param connection The {@code RemoteConnection} invoking this method. + * @param callSubstate The new call substate of the {@code RemoteConnection}. + * @hide + */ + public void onCallSubstateChanged(RemoteConnection connection, int callSubstate) {} + + /** * Indicates that this {@code RemoteConnection} has been destroyed. No further requests * should be made to the {@code RemoteConnection}, and references to it should be cleared. * @@ -223,11 +233,13 @@ public final class RemoteConnection { public void onPeerDimensionsChanged(VideoProvider videoProvider, int width, int height) {} - public void onCallDataUsageChanged(VideoProvider videoProvider, int dataUsage) {} + public void onCallDataUsageChanged(VideoProvider videoProvider, long dataUsage) {} public void onCameraCapabilitiesChanged( VideoProvider videoProvider, CameraCapabilities cameraCapabilities) {} + + public void onVideoQualityChanged(VideoProvider videoProvider, int videoQuality) {} } private final IVideoCallback mVideoCallbackDelegate = new IVideoCallback() { @@ -265,7 +277,7 @@ public final class RemoteConnection { } @Override - public void changeCallDataUsage(int dataUsage) { + public void changeCallDataUsage(long dataUsage) { for (Listener l : mListeners) { l.onCallDataUsageChanged(VideoProvider.this, dataUsage); } @@ -279,6 +291,13 @@ public final class RemoteConnection { } @Override + public void changeVideoQuality(int videoQuality) { + for (Listener l : mListeners) { + l.onVideoQualityChanged(VideoProvider.this, videoQuality); + } + } + + @Override public IBinder asBinder() { return null; } @@ -403,6 +422,7 @@ public final class RemoteConnection { private boolean mConnected; private int mConnectionCapabilities; private int mVideoState; + private int mCallSubstate; private VideoProvider mVideoProvider; private boolean mIsVoipAudioMode; private StatusHints mStatusHints; @@ -583,8 +603,16 @@ public final class RemoteConnection { } /** - * Obtains the video provider of this {@code RemoteConnection}. * + * @return The call substate of the {@code RemoteConnection}. See + * @hide + */ + public int getCallSubstate() { + return mCallSubstate; + } + + /** + * Obtains the video provider of this {@code RemoteConnection}. * @return The video provider associated with this {@code RemoteConnection}. * @hide */ @@ -897,6 +925,16 @@ public final class RemoteConnection { /** * @hide */ + void setCallSubstate(int callSubstate) { + mCallSubstate = callSubstate; + for (Callback c : mCallbacks) { + c.onCallSubstateChanged(this, callSubstate); + } + } + + /** + * @hide + */ void setVideoProvider(VideoProvider videoProvider) { mVideoProvider = videoProvider; for (Callback c : mCallbacks) { diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java index 43a92cb..179db55 100644 --- a/telecomm/java/android/telecom/RemoteConnectionService.java +++ b/telecomm/java/android/telecom/RemoteConnectionService.java @@ -79,6 +79,7 @@ final class RemoteConnectionService { } connection.setConferenceableConnections(conferenceable); connection.setVideoState(parcel.getVideoState()); + connection.setCallSubstate(parcel.getCallSubstate()); if (connection.getState() == Connection.STATE_DISCONNECTED) { // ... then, if it was created in a disconnected state, that indicates // failure on the providing end, so immediately mark it destroyed @@ -306,6 +307,12 @@ final class RemoteConnectionService { mOurConnectionServiceImpl.addRemoteExistingConnection(remoteConnction); } + + @Override + public void setCallSubstate(String callId, int callSubstate) { + findConnectionForAction(callId, "callSubstate") + .setCallSubstate(callSubstate); + } }; private final ConnectionServiceAdapterServant mServant = diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java index 925058e..0445448 100644 --- a/telecomm/java/android/telecom/VideoCallImpl.java +++ b/telecomm/java/android/telecom/VideoCallImpl.java @@ -42,6 +42,7 @@ public class VideoCallImpl extends VideoCall { private static final int MSG_CHANGE_PEER_DIMENSIONS = 4; private static final int MSG_CHANGE_CALL_DATA_USAGE = 5; private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 6; + private static final int MSG_CHANGE_VIDEO_QUALITY = 7; private final IVideoProvider mVideoProvider; private final VideoCallListenerBinder mBinder; @@ -88,7 +89,12 @@ public class VideoCallImpl extends VideoCall { } @Override - public void changeCallDataUsage(int dataUsage) { + public void changeVideoQuality(int videoQuality) { + mHandler.obtainMessage(MSG_CHANGE_VIDEO_QUALITY, videoQuality, 0).sendToTarget(); + } + + @Override + public void changeCallDataUsage(long dataUsage) { mHandler.obtainMessage(MSG_CHANGE_CALL_DATA_USAGE, dataUsage).sendToTarget(); } @@ -139,12 +145,15 @@ public class VideoCallImpl extends VideoCall { } break; case MSG_CHANGE_CALL_DATA_USAGE: - mVideoCallListener.onCallDataUsageChanged(msg.arg1); + mVideoCallListener.onCallDataUsageChanged((long) msg.obj); break; case MSG_CHANGE_CAMERA_CAPABILITIES: mVideoCallListener.onCameraCapabilitiesChanged( (CameraCapabilities) msg.obj); break; + case MSG_CHANGE_VIDEO_QUALITY: + mVideoCallListener.onVideoQualityChanged(msg.arg1); + break; default: break; } @@ -244,4 +253,4 @@ public class VideoCallImpl extends VideoCall { } catch (RemoteException e) { } } -} \ No newline at end of file +} diff --git a/telecomm/java/android/telecom/VideoCallbackServant.java b/telecomm/java/android/telecom/VideoCallbackServant.java index d0e3f22..1123621 100644 --- a/telecomm/java/android/telecom/VideoCallbackServant.java +++ b/telecomm/java/android/telecom/VideoCallbackServant.java @@ -38,6 +38,7 @@ final class VideoCallbackServant { private static final int MSG_CHANGE_PEER_DIMENSIONS = 3; private static final int MSG_CHANGE_CALL_DATA_USAGE = 4; private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 5; + private static final int MSG_CHANGE_VIDEO_QUALITY = 6; private final IVideoCallback mDelegate; @@ -90,7 +91,7 @@ final class VideoCallbackServant { case MSG_CHANGE_CALL_DATA_USAGE: { SomeArgs args = (SomeArgs) msg.obj; try { - mDelegate.changeCallDataUsage(args.argi1); + mDelegate.changeCallDataUsage((long) args.arg1); } finally { args.recycle(); } @@ -100,6 +101,10 @@ final class VideoCallbackServant { mDelegate.changeCameraCapabilities((CameraCapabilities) msg.obj); break; } + case MSG_CHANGE_VIDEO_QUALITY: { + mDelegate.changeVideoQuality(msg.arg1); + break; + } } } }; @@ -136,9 +141,9 @@ final class VideoCallbackServant { } @Override - public void changeCallDataUsage(int dataUsage) throws RemoteException { + public void changeCallDataUsage(long dataUsage) throws RemoteException { SomeArgs args = SomeArgs.obtain(); - args.argi1 = dataUsage; + args.arg1 = dataUsage; mHandler.obtainMessage(MSG_CHANGE_CALL_DATA_USAGE, args).sendToTarget(); } @@ -148,6 +153,11 @@ final class VideoCallbackServant { mHandler.obtainMessage(MSG_CHANGE_CAMERA_CAPABILITIES, cameraCapabilities) .sendToTarget(); } + + @Override + public void changeVideoQuality(int videoQuality) throws RemoteException { + mHandler.obtainMessage(MSG_CHANGE_VIDEO_QUALITY, videoQuality, 0).sendToTarget(); + } }; public VideoCallbackServant(IVideoCallback delegate) { diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java index e62e994..2fd438a 100644 --- a/telecomm/java/android/telecom/VideoProfile.java +++ b/telecomm/java/android/telecom/VideoProfile.java @@ -24,6 +24,11 @@ import android.os.Parcelable; */ public class VideoProfile implements Parcelable { /** + * "Unknown" video quality. + * @hide + */ + public static final int QUALITY_UNKNOWN = 0; + /** * "High" video quality. */ public static final int QUALITY_HIGH = 1; @@ -179,6 +184,17 @@ public class VideoProfile implements Parcelable { } /** + * Whether the video state is any of the video type + * @param videoState The video state. + * @hide + * @return Returns true if the video state TX or RX or Bidirectional + */ + public static boolean isVideo(int videoState) { + return hasState(videoState, TX_ENABLED) || hasState(videoState, RX_ENABLED) + || hasState(videoState, BIDIRECTIONAL); + } + + /** * Whether the video transmission is enabled. * @param videoState The video state. * @return Returns true if the video transmission is enabled. diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl index 7e7e9cc..e6c28f3 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl @@ -81,4 +81,6 @@ oneway interface IConnectionServiceAdapter { void setConferenceableConnections(String callId, in List conferenceableCallIds); void addExistingConnection(String callId, in ParcelableConnection connection); + + void setCallSubstate(String callId, int callSubstate); } diff --git a/telecomm/java/com/android/internal/telecom/IVideoCallback.aidl b/telecomm/java/com/android/internal/telecom/IVideoCallback.aidl index f758b60..59f8f0c 100644 --- a/telecomm/java/com/android/internal/telecom/IVideoCallback.aidl +++ b/telecomm/java/com/android/internal/telecom/IVideoCallback.aidl @@ -39,7 +39,9 @@ oneway interface IVideoCallback { void changePeerDimensions(int width, int height); - void changeCallDataUsage(int dataUsage); + void changeCallDataUsage(long dataUsage); void changeCameraCapabilities(in CameraCapabilities cameraCapabilities); + + void changeVideoQuality(int videoQuality); } diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java index 239c16a..604d32d 100644 --- a/telephony/java/com/android/ims/ImsCallProfile.java +++ b/telephony/java/com/android/ims/ImsCallProfile.java @@ -270,7 +270,6 @@ public class ImsCallProfile implements Parcelable { return "{ serviceType=" + mServiceType + ", callType=" + mCallType + ", restrictCause=" + mRestrictCause + - //", callExtras=" + mCallExtras.toString() + ", mediaProfile=" + mMediaProfile.toString() + " }"; } @@ -313,22 +312,31 @@ public class ImsCallProfile implements Parcelable { * @param callType The call type. * @return The video state. */ - public static int getVideoStateFromCallType(int callType) { - switch (callType) { - case CALL_TYPE_VT_NODIR: - return VideoProfile.VideoState.PAUSED | - VideoProfile.VideoState.BIDIRECTIONAL; + public static int getVideoStateFromImsCallProfile(ImsCallProfile callProfile) { + int videostate = VideoProfile.VideoState.AUDIO_ONLY; + switch (callProfile.mCallType) { case CALL_TYPE_VT_TX: - return VideoProfile.VideoState.TX_ENABLED; + videostate = VideoProfile.VideoState.TX_ENABLED; + break; case CALL_TYPE_VT_RX: - return VideoProfile.VideoState.RX_ENABLED; + videostate = VideoProfile.VideoState.RX_ENABLED; + break; case CALL_TYPE_VT: - return VideoProfile.VideoState.BIDIRECTIONAL; + videostate = VideoProfile.VideoState.BIDIRECTIONAL; + break; case CALL_TYPE_VOICE: - return VideoProfile.VideoState.AUDIO_ONLY; + videostate = VideoProfile.VideoState.AUDIO_ONLY; + break; default: - return VideoProfile.VideoState.AUDIO_ONLY; + videostate = VideoProfile.VideoState.AUDIO_ONLY; + break; } + if (callProfile.isVideoPaused() && videostate != VideoProfile.VideoState.AUDIO_ONLY) { + videostate |= VideoProfile.VideoState.PAUSED; + } else { + videostate &= ~VideoProfile.VideoState.PAUSED; + } + return videostate; } /** @@ -387,6 +395,14 @@ public class ImsCallProfile implements Parcelable { } /** + * Checks if video call is paused + * @return true if call is video paused + */ + public boolean isVideoPaused() { + return mMediaProfile.mVideoDirection == ImsStreamMediaProfile.DIRECTION_INACTIVE; + } + + /** * Determines if a video state is set in a video state bit-mask. * * @param videoState The video state bit mask. diff --git a/telephony/java/com/android/ims/ImsConfigListener.aidl b/telephony/java/com/android/ims/ImsConfigListener.aidl index e827774..64a5015 100644 --- a/telephony/java/com/android/ims/ImsConfigListener.aidl +++ b/telephony/java/com/android/ims/ImsConfigListener.aidl @@ -48,4 +48,26 @@ oneway interface ImsConfigListener { * @return void. */ void onSetFeatureResponse(int feature, int network, int value, int status); -} \ No newline at end of file + + /** + * Notifies client the value of the get operation result on the video quality item. + * + * @param status. as defined in com.android.ims.ImsConfig#OperationStatusConstants. + * @param quality. as defined in com.android.ims.ImsConfig#OperationValuesConstants. + * @return void + * + * @throws ImsException if calling the IMS service results in an error. + */ + void onGetVideoQuality(int status, int quality); + + /** + * Notifies client the set value operation result for video quality item. + * Used by clients that need to be notified the set operation result. + * + * @param status. as defined in com.android.ims.ImsConfig#OperationStatusConstants. + * @return void + * + * @throws ImsException if calling the IMS service results in an error. + */ + void onSetVideoQuality(int status); +} diff --git a/telephony/java/com/android/ims/internal/IImsCallSession.aidl b/telephony/java/com/android/ims/internal/IImsCallSession.aidl index b1f2d32..9b435dc 100644 --- a/telephony/java/com/android/ims/internal/IImsCallSession.aidl +++ b/telephony/java/com/android/ims/internal/IImsCallSession.aidl @@ -255,4 +255,11 @@ interface IImsCallSession { * @return {@code True} if the session is multiparty. */ boolean isMultiparty(); + + /** + * Gets the call substate for this session. + * + * @return the call substate for this session. + */ + int getCallSubstate(); } diff --git a/telephony/java/com/android/ims/internal/IImsConfig.aidl b/telephony/java/com/android/ims/internal/IImsConfig.aidl index 441e03e..7324814 100644 --- a/telephony/java/com/android/ims/internal/IImsConfig.aidl +++ b/telephony/java/com/android/ims/internal/IImsConfig.aidl @@ -100,4 +100,24 @@ interface IImsConfig { * @return void */ boolean getVolteProvisioned(); + + /** + * + * Gets the value for ims fature item video quality. + * + * @param listener. Video quality value returned asynchronously through listener. + * @return void + */ + oneway void getVideoQuality(ImsConfigListener listener); + + /** + * Sets the value for IMS feature item video quality. + * + * @param quality, defines the value of video quality. + * @param listener, provided if caller needs to be notified for set result. + * @return void + * + * @throws ImsException if calling the IMS service results in an error. + */ + oneway void setVideoQuality(int quality, ImsConfigListener listener); } diff --git a/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl b/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl index f867fcb..be8751b 100644 --- a/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl +++ b/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl @@ -41,7 +41,9 @@ oneway interface IImsVideoCallCallback { void changePeerDimensions(int width, int height); - void changeCallDataUsage(int dataUsage); + void changeCallDataUsage(long dataUsage); void changeCameraCapabilities(in CameraCapabilities cameraCapabilities); + + void changeVideoQuality(int videoQuality); } diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java index b8e8064..0ebd719 100644 --- a/telephony/java/com/android/internal/telephony/PhoneConstants.java +++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java @@ -186,4 +186,11 @@ public class PhoneConstants { //FIXME maybe this shouldn't be here - sprout only public static final int CAPABILITY_3G = 1; + + /** + * Values for the adb property "persist.radio.videocall.audio.output" + */ + public static final int AUDIO_OUTPUT_ENABLE_SPEAKER = 0; + public static final int AUDIO_OUTPUT_DISABLE_SPEAKER = 1; + public static final int AUDIO_OUTPUT_DEFAULT = AUDIO_OUTPUT_ENABLE_SPEAKER; } diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index c89208d..645c3a1 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -209,4 +209,12 @@ public interface TelephonyProperties * Set to the sim count. */ static final String PROPERTY_SIM_COUNT = "ro.telephony.sim.count"; + + /** + * Controls audio route for video calls. + * 0 - Use the default audio routing strategy. + * 1 - Disable the speaker. Route the audio to Headset or Bluetooth + * or Earpiece, based on the default audio routing strategy. + */ + static final String PROPERTY_VIDEOCALL_AUDIO_OUTPUT = "persist.radio.call.audio.output"; } -- cgit v1.1