Merge changes from topic "ims_apis"

* changes:
  Modify ImsService API to accomodate compat
  Make ImsService API @SystemApi
  Integrate new MMTel APIs into the framework
  Integrate ImsCallSessionListener API changes
diff --git a/Android.bp b/Android.bp
index 0cd985d..985d734 100644
--- a/Android.bp
+++ b/Android.bp
@@ -462,16 +462,19 @@
         "telecomm/java/com/android/internal/telecom/RemoteServiceCallback.aidl",
         "telephony/java/android/telephony/data/IDataService.aidl",
         "telephony/java/android/telephony/data/IDataServiceCallback.aidl",
-        "telephony/java/android/telephony/ims/internal/aidl/IImsCallSessionListener.aidl",
-        "telephony/java/android/telephony/ims/internal/aidl/IImsCapabilityCallback.aidl",
-        "telephony/java/android/telephony/ims/internal/aidl/IImsConfig.aidl",
-        "telephony/java/android/telephony/ims/internal/aidl/IImsConfigCallback.aidl",
-        "telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl",
-        "telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl",
-        "telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl",
-        "telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl",
-        "telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl",
-	"telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl",
+        "telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl",
+        "telephony/java/android/telephony/ims/aidl/IImsCapabilityCallback.aidl",
+        "telephony/java/android/telephony/ims/aidl/IImsConfig.aidl",
+        "telephony/java/android/telephony/ims/aidl/IImsConfigCallback.aidl",
+        "telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl",
+        "telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl",
+        "telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl",
+        "telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl",
+        "telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl",
+        "telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl",
+        "telephony/java/android/telephony/ims/aidl/IImsServiceControllerListener.aidl",
+	    "telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl",
+        "telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl",
         "telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl",
         "telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl",
         "telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl",
@@ -489,13 +492,10 @@
         "telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl",
         "telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl",
         "telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl",
-        "telephony/java/com/android/ims/internal/IImsRegistration.aidl",
-        "telephony/java/com/android/ims/internal/IImsRegistrationCallback.aidl",
         "telephony/java/com/android/ims/internal/IImsRcsFeature.aidl",
         "telephony/java/com/android/ims/internal/IImsService.aidl",
         "telephony/java/com/android/ims/internal/IImsServiceController.aidl",
         "telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl",
-	"telephony/java/com/android/ims/internal/IImsSmsListener.aidl",
         "telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl",
         "telephony/java/com/android/ims/internal/IImsUt.aidl",
         "telephony/java/com/android/ims/internal/IImsUtListener.aidl",
diff --git a/api/system-current.txt b/api/system-current.txt
index 0371f91..97e8264 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4300,16 +4300,669 @@
 
 package android.telephony.ims {
 
+  public final class ImsCallForwardInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getCondition();
+    method public java.lang.String getNumber();
+    method public int getServiceClass();
+    method public int getStatus();
+    method public int getTimeSeconds();
+    method public int getToA();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallForwardInfo> CREATOR;
+  }
+
+  public final class ImsCallProfile implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.String getCallExtra(java.lang.String);
+    method public java.lang.String getCallExtra(java.lang.String, java.lang.String);
+    method public boolean getCallExtraBoolean(java.lang.String);
+    method public boolean getCallExtraBoolean(java.lang.String, boolean);
+    method public int getCallExtraInt(java.lang.String);
+    method public int getCallExtraInt(java.lang.String, int);
+    method public android.os.Bundle getCallExtras();
+    method public int getCallType();
+    method public static int getCallTypeFromVideoState(int);
+    method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
+    method public int getRestrictCause();
+    method public int getServiceType();
+    method public static int getVideoStateFromCallType(int);
+    method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile);
+    method public boolean isVideoCall();
+    method public boolean isVideoPaused();
+    method public static int presentationToOir(int);
+    method public void setCallExtra(java.lang.String, java.lang.String);
+    method public void setCallExtraBoolean(java.lang.String, boolean);
+    method public void setCallExtraInt(java.lang.String, int);
+    method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
+    method public void updateCallType(android.telephony.ims.ImsCallProfile);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CALL_RESTRICT_CAUSE_DISABLED = 2; // 0x2
+    field public static final int CALL_RESTRICT_CAUSE_HD = 3; // 0x3
+    field public static final int CALL_RESTRICT_CAUSE_NONE = 0; // 0x0
+    field public static final int CALL_RESTRICT_CAUSE_RAT = 1; // 0x1
+    field public static final int CALL_TYPE_VIDEO_N_VOICE = 3; // 0x3
+    field public static final int CALL_TYPE_VOICE = 2; // 0x2
+    field public static final int CALL_TYPE_VOICE_N_VIDEO = 1; // 0x1
+    field public static final int CALL_TYPE_VS = 8; // 0x8
+    field public static final int CALL_TYPE_VS_RX = 10; // 0xa
+    field public static final int CALL_TYPE_VS_TX = 9; // 0x9
+    field public static final int CALL_TYPE_VT = 4; // 0x4
+    field public static final int CALL_TYPE_VT_NODIR = 7; // 0x7
+    field public static final int CALL_TYPE_VT_RX = 6; // 0x6
+    field public static final int CALL_TYPE_VT_TX = 5; // 0x5
+    field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallProfile> CREATOR;
+    field public static final int DIALSTRING_NORMAL = 0; // 0x0
+    field public static final int DIALSTRING_SS_CONF = 1; // 0x1
+    field public static final int DIALSTRING_USSD = 2; // 0x2
+    field public static final java.lang.String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
+    field public static final java.lang.String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
+    field public static final java.lang.String EXTRA_CHILD_NUMBER = "ChildNum";
+    field public static final java.lang.String EXTRA_CNA = "cna";
+    field public static final java.lang.String EXTRA_CNAP = "cnap";
+    field public static final java.lang.String EXTRA_CODEC = "Codec";
+    field public static final java.lang.String EXTRA_DIALSTRING = "dialstring";
+    field public static final java.lang.String EXTRA_DISPLAY_TEXT = "DisplayText";
+    field public static final java.lang.String EXTRA_IS_CALL_PULL = "CallPull";
+    field public static final java.lang.String EXTRA_OI = "oi";
+    field public static final java.lang.String EXTRA_OIR = "oir";
+    field public static final java.lang.String EXTRA_REMOTE_URI = "remote_uri";
+    field public static final java.lang.String EXTRA_USSD = "ussd";
+    field public static final int OIR_DEFAULT = 0; // 0x0
+    field public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2; // 0x2
+    field public static final int OIR_PRESENTATION_PAYPHONE = 4; // 0x4
+    field public static final int OIR_PRESENTATION_RESTRICTED = 1; // 0x1
+    field public static final int OIR_PRESENTATION_UNKNOWN = 3; // 0x3
+    field public static final int SERVICE_TYPE_EMERGENCY = 2; // 0x2
+    field public static final int SERVICE_TYPE_NONE = 0; // 0x0
+    field public static final int SERVICE_TYPE_NORMAL = 1; // 0x1
+  }
+
+  public class ImsCallSessionListener {
+    method public void callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo);
+    method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
+    method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
+    method public void callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState);
+    method public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo);
+    method public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo);
+    method public void callSessionHeld(android.telephony.ims.ImsCallProfile);
+    method public void callSessionHoldFailed(android.telephony.ims.ImsReasonInfo);
+    method public void callSessionHoldReceived(android.telephony.ims.ImsCallProfile);
+    method public void callSessionInitiated(android.telephony.ims.ImsCallProfile);
+    method public void callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo);
+    method public void callSessionInviteParticipantsRequestDelivered();
+    method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
+    method public void callSessionMayHandover(int, int);
+    method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase);
+    method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo);
+    method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
+    method public void callSessionMultipartyStateChanged(boolean);
+    method public void callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile);
+    method public void callSessionRemoveParticipantsRequestDelivered();
+    method public void callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
+    method public void callSessionResumeFailed(android.telephony.ims.ImsReasonInfo);
+    method public void callSessionResumeReceived(android.telephony.ims.ImsCallProfile);
+    method public void callSessionResumed(android.telephony.ims.ImsCallProfile);
+    method public void callSessionRttMessageReceived(java.lang.String);
+    method public void callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile);
+    method public void callSessionRttModifyResponseReceived(int);
+    method public void callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification);
+    method public void callSessionTerminated(android.telephony.ims.ImsReasonInfo);
+    method public void callSessionTtyModeReceived(int);
+    method public void callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo);
+    method public void callSessionUpdateReceived(android.telephony.ims.ImsCallProfile);
+    method public void callSessionUpdated(android.telephony.ims.ImsCallProfile);
+    method public void callSessionUssdMessageReceived(int, java.lang.String);
+  }
+
+  public final class ImsConferenceState implements android.os.Parcelable {
+    method public int describeContents();
+    method public static int getConnectionStateForStatus(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsConferenceState> CREATOR;
+    field public static final java.lang.String DISPLAY_TEXT = "display-text";
+    field public static final java.lang.String ENDPOINT = "endpoint";
+    field public static final java.lang.String SIP_STATUS_CODE = "sipstatuscode";
+    field public static final java.lang.String STATUS = "status";
+    field public static final java.lang.String STATUS_ALERTING = "alerting";
+    field public static final java.lang.String STATUS_CONNECTED = "connected";
+    field public static final java.lang.String STATUS_CONNECT_FAIL = "connect-fail";
+    field public static final java.lang.String STATUS_DIALING_IN = "dialing-in";
+    field public static final java.lang.String STATUS_DIALING_OUT = "dialing-out";
+    field public static final java.lang.String STATUS_DISCONNECTED = "disconnected";
+    field public static final java.lang.String STATUS_DISCONNECTING = "disconnecting";
+    field public static final java.lang.String STATUS_MUTED_VIA_FOCUS = "muted-via-focus";
+    field public static final java.lang.String STATUS_ON_HOLD = "on-hold";
+    field public static final java.lang.String STATUS_PENDING = "pending";
+    field public static final java.lang.String STATUS_SEND_ONLY = "sendonly";
+    field public static final java.lang.String STATUS_SEND_RECV = "sendrecv";
+    field public static final java.lang.String USER = "user";
+    field public final java.util.HashMap<java.lang.String, android.os.Bundle> mParticipants;
+  }
+
+  public final class ImsExternalCallState implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.net.Uri getAddress();
+    method public int getCallId();
+    method public int getCallState();
+    method public int getCallType();
+    method public boolean isCallHeld();
+    method public boolean isCallPullable();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CALL_STATE_CONFIRMED = 1; // 0x1
+    field public static final int CALL_STATE_TERMINATED = 2; // 0x2
+    field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR;
+  }
+
+  public final class ImsReasonInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getCode();
+    method public int getExtraCode();
+    method public java.lang.String getExtraMessage();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CODE_ACCESS_CLASS_BLOCKED = 1512; // 0x5e8
+    field public static final int CODE_ANSWERED_ELSEWHERE = 1014; // 0x3f6
+    field public static final int CODE_BLACKLISTED_CALL_ID = 506; // 0x1fa
+    field public static final int CODE_CALL_BARRED = 240; // 0xf0
+    field public static final int CODE_CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE = 1100; // 0x44c
+    field public static final int CODE_CALL_END_CAUSE_CALL_PULL = 1016; // 0x3f8
+    field public static final int CODE_CALL_PULL_OUT_OF_SYNC = 1015; // 0x3f7
+    field public static final int CODE_DATA_DISABLED = 1406; // 0x57e
+    field public static final int CODE_DATA_LIMIT_REACHED = 1405; // 0x57d
+    field public static final int CODE_DIAL_MODIFIED_TO_DIAL = 246; // 0xf6
+    field public static final int CODE_DIAL_MODIFIED_TO_DIAL_VIDEO = 247; // 0xf7
+    field public static final int CODE_DIAL_MODIFIED_TO_SS = 245; // 0xf5
+    field public static final int CODE_DIAL_MODIFIED_TO_USSD = 244; // 0xf4
+    field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_DIAL = 248; // 0xf8
+    field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO = 249; // 0xf9
+    field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_SS = 250; // 0xfa
+    field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_USSD = 251; // 0xfb
+    field public static final int CODE_ECBM_NOT_SUPPORTED = 901; // 0x385
+    field public static final int CODE_EMERGENCY_PERM_FAILURE = 364; // 0x16c
+    field public static final int CODE_EMERGENCY_TEMP_FAILURE = 363; // 0x16b
+    field public static final int CODE_EPDG_TUNNEL_ESTABLISH_FAILURE = 1400; // 0x578
+    field public static final int CODE_EPDG_TUNNEL_LOST_CONNECTION = 1402; // 0x57a
+    field public static final int CODE_EPDG_TUNNEL_REKEY_FAILURE = 1401; // 0x579
+    field public static final int CODE_FDN_BLOCKED = 241; // 0xf1
+    field public static final int CODE_IKEV2_AUTH_FAILURE = 1408; // 0x580
+    field public static final int CODE_IMEI_NOT_ACCEPTED = 243; // 0xf3
+    field public static final int CODE_IWLAN_DPD_FAILURE = 1300; // 0x514
+    field public static final int CODE_LOCAL_CALL_BUSY = 142; // 0x8e
+    field public static final int CODE_LOCAL_CALL_CS_RETRY_REQUIRED = 146; // 0x92
+    field public static final int CODE_LOCAL_CALL_DECLINE = 143; // 0x8f
+    field public static final int CODE_LOCAL_CALL_EXCEEDED = 141; // 0x8d
+    field public static final int CODE_LOCAL_CALL_RESOURCE_RESERVATION_FAILED = 145; // 0x91
+    field public static final int CODE_LOCAL_CALL_TERMINATED = 148; // 0x94
+    field public static final int CODE_LOCAL_CALL_VCC_ON_PROGRESSING = 144; // 0x90
+    field public static final int CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED = 147; // 0x93
+    field public static final int CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE = 108; // 0x6c
+    field public static final int CODE_LOCAL_HO_NOT_FEASIBLE = 149; // 0x95
+    field public static final int CODE_LOCAL_ILLEGAL_ARGUMENT = 101; // 0x65
+    field public static final int CODE_LOCAL_ILLEGAL_STATE = 102; // 0x66
+    field public static final int CODE_LOCAL_IMS_SERVICE_DOWN = 106; // 0x6a
+    field public static final int CODE_LOCAL_INTERNAL_ERROR = 103; // 0x67
+    field public static final int CODE_LOCAL_LOW_BATTERY = 112; // 0x70
+    field public static final int CODE_LOCAL_NETWORK_IP_CHANGED = 124; // 0x7c
+    field public static final int CODE_LOCAL_NETWORK_NO_LTE_COVERAGE = 122; // 0x7a
+    field public static final int CODE_LOCAL_NETWORK_NO_SERVICE = 121; // 0x79
+    field public static final int CODE_LOCAL_NETWORK_ROAMING = 123; // 0x7b
+    field public static final int CODE_LOCAL_NOT_REGISTERED = 132; // 0x84
+    field public static final int CODE_LOCAL_NO_PENDING_CALL = 107; // 0x6b
+    field public static final int CODE_LOCAL_POWER_OFF = 111; // 0x6f
+    field public static final int CODE_LOCAL_SERVICE_UNAVAILABLE = 131; // 0x83
+    field public static final int CODE_LOW_BATTERY = 505; // 0x1f9
+    field public static final int CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED = 1403; // 0x57b
+    field public static final int CODE_MEDIA_INIT_FAILED = 401; // 0x191
+    field public static final int CODE_MEDIA_NOT_ACCEPTABLE = 403; // 0x193
+    field public static final int CODE_MEDIA_NO_DATA = 402; // 0x192
+    field public static final int CODE_MEDIA_UNSPECIFIED = 404; // 0x194
+    field public static final int CODE_MULTIENDPOINT_NOT_SUPPORTED = 902; // 0x386
+    field public static final int CODE_NETWORK_DETACH = 1513; // 0x5e9
+    field public static final int CODE_NETWORK_REJECT = 1504; // 0x5e0
+    field public static final int CODE_NETWORK_RESP_TIMEOUT = 1503; // 0x5df
+    field public static final int CODE_NO_VALID_SIM = 1501; // 0x5dd
+    field public static final int CODE_OEM_CAUSE_1 = 61441; // 0xf001
+    field public static final int CODE_OEM_CAUSE_10 = 61450; // 0xf00a
+    field public static final int CODE_OEM_CAUSE_11 = 61451; // 0xf00b
+    field public static final int CODE_OEM_CAUSE_12 = 61452; // 0xf00c
+    field public static final int CODE_OEM_CAUSE_13 = 61453; // 0xf00d
+    field public static final int CODE_OEM_CAUSE_14 = 61454; // 0xf00e
+    field public static final int CODE_OEM_CAUSE_15 = 61455; // 0xf00f
+    field public static final int CODE_OEM_CAUSE_2 = 61442; // 0xf002
+    field public static final int CODE_OEM_CAUSE_3 = 61443; // 0xf003
+    field public static final int CODE_OEM_CAUSE_4 = 61444; // 0xf004
+    field public static final int CODE_OEM_CAUSE_5 = 61445; // 0xf005
+    field public static final int CODE_OEM_CAUSE_6 = 61446; // 0xf006
+    field public static final int CODE_OEM_CAUSE_7 = 61447; // 0xf007
+    field public static final int CODE_OEM_CAUSE_8 = 61448; // 0xf008
+    field public static final int CODE_OEM_CAUSE_9 = 61449; // 0xf009
+    field public static final int CODE_RADIO_ACCESS_FAILURE = 1505; // 0x5e1
+    field public static final int CODE_RADIO_INTERNAL_ERROR = 1502; // 0x5de
+    field public static final int CODE_RADIO_LINK_FAILURE = 1506; // 0x5e2
+    field public static final int CODE_RADIO_LINK_LOST = 1507; // 0x5e3
+    field public static final int CODE_RADIO_OFF = 1500; // 0x5dc
+    field public static final int CODE_RADIO_RELEASE_ABNORMAL = 1511; // 0x5e7
+    field public static final int CODE_RADIO_RELEASE_NORMAL = 1510; // 0x5e6
+    field public static final int CODE_RADIO_SETUP_FAILURE = 1509; // 0x5e5
+    field public static final int CODE_RADIO_UPLINK_FAILURE = 1508; // 0x5e4
+    field public static final int CODE_REGISTRATION_ERROR = 1000; // 0x3e8
+    field public static final int CODE_REMOTE_CALL_DECLINE = 1404; // 0x57c
+    field public static final int CODE_SIP_ALTERNATE_EMERGENCY_CALL = 1514; // 0x5ea
+    field public static final int CODE_SIP_BAD_ADDRESS = 337; // 0x151
+    field public static final int CODE_SIP_BAD_REQUEST = 331; // 0x14b
+    field public static final int CODE_SIP_BUSY = 338; // 0x152
+    field public static final int CODE_SIP_CLIENT_ERROR = 342; // 0x156
+    field public static final int CODE_SIP_FORBIDDEN = 332; // 0x14c
+    field public static final int CODE_SIP_GLOBAL_ERROR = 362; // 0x16a
+    field public static final int CODE_SIP_NOT_ACCEPTABLE = 340; // 0x154
+    field public static final int CODE_SIP_NOT_FOUND = 333; // 0x14d
+    field public static final int CODE_SIP_NOT_REACHABLE = 341; // 0x155
+    field public static final int CODE_SIP_NOT_SUPPORTED = 334; // 0x14e
+    field public static final int CODE_SIP_REDIRECTED = 321; // 0x141
+    field public static final int CODE_SIP_REQUEST_CANCELLED = 339; // 0x153
+    field public static final int CODE_SIP_REQUEST_TIMEOUT = 335; // 0x14f
+    field public static final int CODE_SIP_SERVER_ERROR = 354; // 0x162
+    field public static final int CODE_SIP_SERVER_INTERNAL_ERROR = 351; // 0x15f
+    field public static final int CODE_SIP_SERVER_TIMEOUT = 353; // 0x161
+    field public static final int CODE_SIP_SERVICE_UNAVAILABLE = 352; // 0x160
+    field public static final int CODE_SIP_TEMPRARILY_UNAVAILABLE = 336; // 0x150
+    field public static final int CODE_SIP_USER_REJECTED = 361; // 0x169
+    field public static final int CODE_SUPP_SVC_CANCELLED = 1202; // 0x4b2
+    field public static final int CODE_SUPP_SVC_FAILED = 1201; // 0x4b1
+    field public static final int CODE_SUPP_SVC_REINVITE_COLLISION = 1203; // 0x4b3
+    field public static final int CODE_TIMEOUT_1XX_WAITING = 201; // 0xc9
+    field public static final int CODE_TIMEOUT_NO_ANSWER = 202; // 0xca
+    field public static final int CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE = 203; // 0xcb
+    field public static final int CODE_UNSPECIFIED = 0; // 0x0
+    field public static final int CODE_USER_DECLINE = 504; // 0x1f8
+    field public static final int CODE_USER_IGNORE = 503; // 0x1f7
+    field public static final int CODE_USER_NOANSWER = 502; // 0x1f6
+    field public static final int CODE_USER_TERMINATED = 501; // 0x1f5
+    field public static final int CODE_USER_TERMINATED_BY_REMOTE = 510; // 0x1fe
+    field public static final int CODE_UT_CB_PASSWORD_MISMATCH = 821; // 0x335
+    field public static final int CODE_UT_NETWORK_ERROR = 804; // 0x324
+    field public static final int CODE_UT_NOT_SUPPORTED = 801; // 0x321
+    field public static final int CODE_UT_OPERATION_NOT_ALLOWED = 803; // 0x323
+    field public static final int CODE_UT_SERVICE_UNAVAILABLE = 802; // 0x322
+    field public static final int CODE_UT_SS_MODIFIED_TO_DIAL = 822; // 0x336
+    field public static final int CODE_UT_SS_MODIFIED_TO_DIAL_VIDEO = 825; // 0x339
+    field public static final int CODE_UT_SS_MODIFIED_TO_SS = 824; // 0x338
+    field public static final int CODE_UT_SS_MODIFIED_TO_USSD = 823; // 0x337
+    field public static final int CODE_WIFI_LOST = 1407; // 0x57f
+    field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsReasonInfo> CREATOR;
+    field public static final int EXTRA_CODE_CALL_RETRY_BY_SETTINGS = 3; // 0x3
+    field public static final int EXTRA_CODE_CALL_RETRY_NORMAL = 1; // 0x1
+    field public static final int EXTRA_CODE_CALL_RETRY_SILENT_REDIAL = 2; // 0x2
+    field public static final java.lang.String EXTRA_MSG_SERVICE_NOT_AUTHORIZED = "Forbidden. Not Authorized for Service";
+  }
+
   public class ImsService extends android.app.Service {
     ctor public ImsService();
+    method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
+    method public android.telephony.ims.feature.RcsFeature createRcsFeature(int);
+    method public void disableIms(int);
+    method public void enableIms(int);
+    method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
+    method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
+    method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException;
+    method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures();
+    method public void readyForFeatureCreation();
+  }
+
+  public final class ImsSsData implements android.os.Parcelable {
+    ctor public ImsSsData();
+    method public int describeContents();
+    method public boolean isTypeBarring();
+    method public boolean isTypeCf();
+    method public boolean isTypeClip();
+    method public boolean isTypeClir();
+    method public boolean isTypeColp();
+    method public boolean isTypeColr();
+    method public boolean isTypeCw();
+    method public boolean isTypeIcb();
+    method public boolean isTypeInterrogation();
+    method public boolean isTypeUnConditional();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsData> CREATOR;
+    field public static final int SS_ACTIVATION = 0; // 0x0
+    field public static final int SS_ALL_BARRING = 18; // 0x12
+    field public static final int SS_ALL_DATA_TELESERVICES = 3; // 0x3
+    field public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5; // 0x5
+    field public static final int SS_ALL_TELESEVICES = 1; // 0x1
+    field public static final int SS_ALL_TELE_AND_BEARER_SERVICES = 0; // 0x0
+    field public static final int SS_BAIC = 16; // 0x10
+    field public static final int SS_BAIC_ROAMING = 17; // 0x11
+    field public static final int SS_BAOC = 13; // 0xd
+    field public static final int SS_BAOIC = 14; // 0xe
+    field public static final int SS_BAOIC_EXC_HOME = 15; // 0xf
+    field public static final int SS_CFU = 0; // 0x0
+    field public static final int SS_CFUT = 6; // 0x6
+    field public static final int SS_CF_ALL = 4; // 0x4
+    field public static final int SS_CF_ALL_CONDITIONAL = 5; // 0x5
+    field public static final int SS_CF_BUSY = 1; // 0x1
+    field public static final int SS_CF_NOT_REACHABLE = 3; // 0x3
+    field public static final int SS_CF_NO_REPLY = 2; // 0x2
+    field public static final int SS_CLIP = 7; // 0x7
+    field public static final int SS_CLIR = 8; // 0x8
+    field public static final int SS_CNAP = 11; // 0xb
+    field public static final int SS_COLP = 9; // 0x9
+    field public static final int SS_COLR = 10; // 0xa
+    field public static final int SS_DEACTIVATION = 1; // 0x1
+    field public static final int SS_ERASURE = 4; // 0x4
+    field public static final int SS_INCOMING_BARRING = 20; // 0x14
+    field public static final int SS_INCOMING_BARRING_ANONYMOUS = 22; // 0x16
+    field public static final int SS_INCOMING_BARRING_DN = 21; // 0x15
+    field public static final int SS_INTERROGATION = 2; // 0x2
+    field public static final int SS_OUTGOING_BARRING = 19; // 0x13
+    field public static final int SS_REGISTRATION = 3; // 0x3
+    field public static final int SS_SMS_SERVICES = 4; // 0x4
+    field public static final int SS_TELEPHONY = 2; // 0x2
+    field public static final int SS_WAIT = 12; // 0xc
+  }
+
+  public final class ImsSsInfo implements android.os.Parcelable {
+    ctor public ImsSsInfo();
+    method public int describeContents();
+    method public java.lang.String getIcbNum();
+    method public int getStatus();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsInfo> CREATOR;
+    field public static final int DISABLED = 0; // 0x0
+    field public static final int ENABLED = 1; // 0x1
+    field public static final int NOT_REGISTERED = -1; // 0xffffffff
+  }
+
+  public final class ImsStreamMediaProfile implements android.os.Parcelable {
+    method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile);
+    method public int describeContents();
+    method public int getAudioDirection();
+    method public int getAudioQuality();
+    method public int getRttMode();
+    method public int getVideoDirection();
+    method public int getVideoQuality();
+    method public boolean isRttCall();
+    method public void setRttMode(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int AUDIO_QUALITY_AMR = 1; // 0x1
+    field public static final int AUDIO_QUALITY_AMR_WB = 2; // 0x2
+    field public static final int AUDIO_QUALITY_EVRC = 4; // 0x4
+    field public static final int AUDIO_QUALITY_EVRC_B = 5; // 0x5
+    field public static final int AUDIO_QUALITY_EVRC_NW = 7; // 0x7
+    field public static final int AUDIO_QUALITY_EVRC_WB = 6; // 0x6
+    field public static final int AUDIO_QUALITY_EVS_FB = 20; // 0x14
+    field public static final int AUDIO_QUALITY_EVS_NB = 17; // 0x11
+    field public static final int AUDIO_QUALITY_EVS_SWB = 19; // 0x13
+    field public static final int AUDIO_QUALITY_EVS_WB = 18; // 0x12
+    field public static final int AUDIO_QUALITY_G711A = 13; // 0xd
+    field public static final int AUDIO_QUALITY_G711AB = 15; // 0xf
+    field public static final int AUDIO_QUALITY_G711U = 11; // 0xb
+    field public static final int AUDIO_QUALITY_G722 = 14; // 0xe
+    field public static final int AUDIO_QUALITY_G723 = 12; // 0xc
+    field public static final int AUDIO_QUALITY_G729 = 16; // 0x10
+    field public static final int AUDIO_QUALITY_GSM_EFR = 8; // 0x8
+    field public static final int AUDIO_QUALITY_GSM_FR = 9; // 0x9
+    field public static final int AUDIO_QUALITY_GSM_HR = 10; // 0xa
+    field public static final int AUDIO_QUALITY_NONE = 0; // 0x0
+    field public static final int AUDIO_QUALITY_QCELP13K = 3; // 0x3
+    field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsStreamMediaProfile> CREATOR;
+    field public static final int DIRECTION_INACTIVE = 0; // 0x0
+    field public static final int DIRECTION_INVALID = -1; // 0xffffffff
+    field public static final int DIRECTION_RECEIVE = 1; // 0x1
+    field public static final int DIRECTION_SEND = 2; // 0x2
+    field public static final int DIRECTION_SEND_RECEIVE = 3; // 0x3
+    field public static final int RTT_MODE_DISABLED = 0; // 0x0
+    field public static final int RTT_MODE_FULL = 1; // 0x1
+    field public static final int VIDEO_QUALITY_NONE = 0; // 0x0
+    field public static final int VIDEO_QUALITY_QCIF = 1; // 0x1
+    field public static final int VIDEO_QUALITY_QVGA_LANDSCAPE = 2; // 0x2
+    field public static final int VIDEO_QUALITY_QVGA_PORTRAIT = 4; // 0x4
+    field public static final int VIDEO_QUALITY_VGA_LANDSCAPE = 8; // 0x8
+    field public static final int VIDEO_QUALITY_VGA_PORTRAIT = 16; // 0x10
+  }
+
+  public final class ImsSuppServiceNotification implements android.os.Parcelable {
+    ctor public ImsSuppServiceNotification(int, int, int, int, java.lang.String, java.lang.String[]);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSuppServiceNotification> CREATOR;
+    field public final int code;
+    field public final java.lang.String[] history;
+    field public final int index;
+    field public final int notificationType;
+    field public final java.lang.String number;
+    field public final int type;
+  }
+
+  public class ImsUtListener {
+    method public void onSupplementaryServiceIndication(android.telephony.ims.ImsSsData);
+    method public void onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]);
+    method public void onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]);
+    method public void onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]);
+    method public void onUtConfigurationQueried(int, android.os.Bundle);
+    method public void onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo);
+    method public void onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo);
+    method public void onUtConfigurationUpdated(int);
+  }
+
+  public abstract class ImsVideoCallProvider {
+    ctor public ImsVideoCallProvider();
+    method public void changeCallDataUsage(long);
+    method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities);
+    method public void changePeerDimensions(int, int);
+    method public void changeVideoQuality(int);
+    method public void handleCallSessionEvent(int);
+    method public abstract void onRequestCallDataUsage();
+    method public abstract void onRequestCameraCapabilities();
+    method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile);
+    method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile);
+    method public abstract void onSetCamera(java.lang.String);
+    method public void onSetCamera(java.lang.String, int);
+    method public abstract void onSetDeviceOrientation(int);
+    method public abstract void onSetDisplaySurface(android.view.Surface);
+    method public abstract void onSetPauseImage(android.net.Uri);
+    method public abstract void onSetPreviewSurface(android.view.Surface);
+    method public abstract void onSetZoom(float);
+    method public void receiveSessionModifyRequest(android.telecom.VideoProfile);
+    method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
   }
 
 }
 
-package android.telephony.ims.internal.stub {
+package android.telephony.ims.feature {
 
-  public class SmsImplBase {
-    ctor public SmsImplBase();
+  public final class CapabilityChangeRequest implements android.os.Parcelable {
+    method public void addCapabilitiesToDisableForTech(int, int);
+    method public void addCapabilitiesToEnableForTech(int, int);
+    method public int describeContents();
+    method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToDisable();
+    method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToEnable();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.ims.feature.CapabilityChangeRequest> CREATOR;
+  }
+
+  public static class CapabilityChangeRequest.CapabilityPair {
+    ctor public CapabilityChangeRequest.CapabilityPair(int, int);
+    method public int getCapability();
+    method public int getRadioTech();
+  }
+
+  public abstract class ImsFeature {
+    ctor public ImsFeature();
+    method public abstract void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+    method public abstract void onFeatureReady();
+    method public abstract void onFeatureRemoved();
+    method public final void setFeatureState(int);
+    field public static final int CAPABILITY_ERROR_GENERIC = -1; // 0xffffffff
+    field public static final int CAPABILITY_SUCCESS = 0; // 0x0
+    field public static final int FEATURE_EMERGENCY_MMTEL = 0; // 0x0
+    field public static final int FEATURE_MMTEL = 1; // 0x1
+    field public static final int FEATURE_RCS = 2; // 0x2
+    field public static final int STATE_INITIALIZING = 1; // 0x1
+    field public static final int STATE_READY = 2; // 0x2
+    field public static final int STATE_UNAVAILABLE = 0; // 0x0
+  }
+
+  protected static class ImsFeature.CapabilityCallbackProxy {
+    method public void onChangeCapabilityConfigurationError(int, int, int);
+  }
+
+  public class MmTelFeature extends android.telephony.ims.feature.ImsFeature {
+    ctor public MmTelFeature();
+    method public void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+    method public android.telephony.ims.ImsCallProfile createCallProfile(int, int);
+    method public android.telephony.ims.stub.ImsCallSessionImplBase createCallSession(android.telephony.ims.ImsCallProfile);
+    method public android.telephony.ims.stub.ImsEcbmImplBase getEcbm();
+    method public android.telephony.ims.stub.ImsMultiEndpointImplBase getMultiEndpoint();
+    method public android.telephony.ims.stub.ImsSmsImplBase getSmsImplementation();
+    method public android.telephony.ims.stub.ImsUtImplBase getUt();
+    method public final void notifyCapabilitiesStatusChanged(android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
+    method public final void notifyIncomingCall(android.telephony.ims.stub.ImsCallSessionImplBase, android.os.Bundle);
+    method public final void notifyVoiceMessageCountUpdate(int);
+    method public void onFeatureReady();
+    method public void onFeatureRemoved();
+    method public boolean queryCapabilityConfiguration(int, int);
+    method public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
+    method public void setUiTtyMode(int, android.os.Message);
+    method public int shouldProcessCall(java.lang.String[]);
+    field public static final int PROCESS_CALL_CSFB = 1; // 0x1
+    field public static final int PROCESS_CALL_EMERGENCY_CSFB = 2; // 0x2
+    field public static final int PROCESS_CALL_IMS = 0; // 0x0
+  }
+
+  public static class MmTelFeature.MmTelCapabilities {
+    ctor public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities);
+    ctor public MmTelFeature.MmTelCapabilities(int);
+    method public final void addCapabilities(int);
+    method public final boolean isCapable(int);
+    method public final void removeCapabilities(int);
+    field public static final int CAPABILITY_TYPE_SMS = 8; // 0x8
+    field public static final int CAPABILITY_TYPE_UT = 4; // 0x4
+    field public static final int CAPABILITY_TYPE_VIDEO = 2; // 0x2
+    field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1
+  }
+
+  public static abstract class MmTelFeature.MmTelCapabilities.MmTelCapability implements java.lang.annotation.Annotation {
+  }
+
+  public static abstract class MmTelFeature.ProcessCallResult implements java.lang.annotation.Annotation {
+  }
+
+  public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
+    ctor public RcsFeature();
+    method public void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+    method public void onFeatureReady();
+    method public void onFeatureRemoved();
+  }
+
+}
+
+package android.telephony.ims.stub {
+
+  public class ImsCallSessionImplBase implements java.lang.AutoCloseable {
+    ctor public ImsCallSessionImplBase();
+    method public void accept(int, android.telephony.ims.ImsStreamMediaProfile);
+    method public void close();
+    method public void extendToConference(java.lang.String[]);
+    method public java.lang.String getCallId();
+    method public android.telephony.ims.ImsCallProfile getCallProfile();
+    method public android.telephony.ims.ImsVideoCallProvider getImsVideoCallProvider();
+    method public android.telephony.ims.ImsCallProfile getLocalCallProfile();
+    method public java.lang.String getProperty(java.lang.String);
+    method public android.telephony.ims.ImsCallProfile getRemoteCallProfile();
+    method public int getState();
+    method public void hold(android.telephony.ims.ImsStreamMediaProfile);
+    method public void inviteParticipants(java.lang.String[]);
+    method public boolean isInCall();
+    method public boolean isMultiparty();
+    method public void merge();
+    method public void reject(int);
+    method public void removeParticipants(java.lang.String[]);
+    method public void resume(android.telephony.ims.ImsStreamMediaProfile);
+    method public void sendDtmf(char, android.os.Message);
+    method public void sendRttMessage(java.lang.String);
+    method public void sendRttModifyRequest(android.telephony.ims.ImsCallProfile);
+    method public void sendRttModifyResponse(boolean);
+    method public void sendUssd(java.lang.String);
+    method public void setListener(android.telephony.ims.ImsCallSessionListener);
+    method public void setMute(boolean);
+    method public void start(java.lang.String, android.telephony.ims.ImsCallProfile);
+    method public void startConference(java.lang.String[], android.telephony.ims.ImsCallProfile);
+    method public void startDtmf(char);
+    method public void stopDtmf();
+    method public void terminate(int);
+    method public void update(int, android.telephony.ims.ImsStreamMediaProfile);
+    field public static final int USSD_MODE_NOTIFY = 0; // 0x0
+    field public static final int USSD_MODE_REQUEST = 1; // 0x1
+  }
+
+  public static class ImsCallSessionImplBase.State {
+    method public static java.lang.String toString(int);
+    field public static final int ESTABLISHED = 4; // 0x4
+    field public static final int ESTABLISHING = 3; // 0x3
+    field public static final int IDLE = 0; // 0x0
+    field public static final int INITIATED = 1; // 0x1
+    field public static final int INVALID = -1; // 0xffffffff
+    field public static final int NEGOTIATING = 2; // 0x2
+    field public static final int REESTABLISHING = 6; // 0x6
+    field public static final int RENEGOTIATING = 5; // 0x5
+    field public static final int TERMINATED = 8; // 0x8
+    field public static final int TERMINATING = 7; // 0x7
+  }
+
+  public class ImsConfigImplBase {
+    ctor public ImsConfigImplBase();
+    method public int getConfigInt(int);
+    method public java.lang.String getConfigString(int);
+    method public final void notifyProvisionedValueChanged(int, int);
+    method public final void notifyProvisionedValueChanged(int, java.lang.String);
+    method public int setConfig(int, int);
+    method public int setConfig(int, java.lang.String);
+    field public static final int CONFIG_RESULT_FAILED = 1; // 0x1
+    field public static final int CONFIG_RESULT_SUCCESS = 0; // 0x0
+    field public static final int CONFIG_RESULT_UNKNOWN = -1; // 0xffffffff
+  }
+
+  public class ImsEcbmImplBase {
+    ctor public ImsEcbmImplBase();
+    method public final void enteredEcbm();
+    method public void exitEmergencyCallbackMode();
+    method public final void exitedEcbm();
+  }
+
+  public final class ImsFeatureConfiguration implements android.os.Parcelable {
+    ctor public ImsFeatureConfiguration();
+    method public int describeContents();
+    method public int[] getServiceFeatures();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.ims.stub.ImsFeatureConfiguration> CREATOR;
+  }
+
+  public static class ImsFeatureConfiguration.Builder {
+    ctor public ImsFeatureConfiguration.Builder();
+    method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int);
+    method public android.telephony.ims.stub.ImsFeatureConfiguration build();
+  }
+
+  public class ImsMultiEndpointImplBase {
+    ctor public ImsMultiEndpointImplBase();
+    method public final void onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>);
+    method public void requestImsExternalCallStateInfo();
+  }
+
+  public class ImsRegistrationImplBase {
+    ctor public ImsRegistrationImplBase();
+    method public final void onDeregistered(android.telephony.ims.ImsReasonInfo);
+    method public final void onRegistered(int);
+    method public final void onRegistering(int);
+    method public final void onSubscriberAssociatedUriChanged(android.net.Uri[]);
+    method public final void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo);
+    field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
+    field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
+    field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
+  }
+
+  public class ImsSmsImplBase {
+    ctor public ImsSmsImplBase();
     method public void acknowledgeSms(int, int, int);
     method public void acknowledgeSmsReport(int, int, int);
     method public java.lang.String getSmsFormat();
@@ -4328,6 +4981,29 @@
     field public static final int STATUS_REPORT_STATUS_OK = 1; // 0x1
   }
 
+  public class ImsUtImplBase {
+    ctor public ImsUtImplBase();
+    method public void close();
+    method public int queryCallBarring(int);
+    method public int queryCallBarringForServiceClass(int, int);
+    method public int queryCallForward(int, java.lang.String);
+    method public int queryCallWaiting();
+    method public int queryClip();
+    method public int queryClir();
+    method public int queryColp();
+    method public int queryColr();
+    method public void setListener(android.telephony.ims.ImsUtListener);
+    method public int transact(android.os.Bundle);
+    method public int updateCallBarring(int, int, java.lang.String[]);
+    method public int updateCallBarringForServiceClass(int, int, java.lang.String[], int);
+    method public int updateCallForward(int, int, java.lang.String, int, int);
+    method public int updateCallWaiting(boolean, int);
+    method public int updateClip(boolean);
+    method public int updateClir(int);
+    method public int updateColp(boolean);
+    method public int updateColr(int);
+  }
+
 }
 
 package android.telephony.mbms {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index dc3195c..78a0ec2 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -27,8 +27,8 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.service.carrier.CarrierService;
+import android.telephony.ims.ImsReasonInfo;
 
-import com.android.ims.ImsReasonInfo;
 import com.android.internal.telephony.ICarrierConfigLoader;
 
 /**
@@ -1423,7 +1423,7 @@
             "allow_video_calling_fallback_bool";
 
     /**
-     * Defines operator-specific {@link com.android.ims.ImsReasonInfo} mappings.
+     * Defines operator-specific {@link ImsReasonInfo} mappings.
      *
      * Format: "ORIGINAL_CODE|MESSAGE|NEW_CODE"
      * Where {@code ORIGINAL_CODE} corresponds to a {@link ImsReasonInfo#getCode()} code,
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 4138e29..96ed20b 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -47,12 +47,13 @@
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telephony.VisualVoicemailService.VisualVoicemailTask;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsMmTelFeature;
+import android.telephony.ims.aidl.IImsRcsFeature;
+import android.telephony.ims.aidl.IImsRegistration;
 import android.telephony.ims.feature.ImsFeature;
 import android.util.Log;
 
-import com.android.ims.internal.IImsMMTelFeature;
-import com.android.ims.internal.IImsRcsFeature;
-import com.android.ims.internal.IImsRegistration;
 import com.android.ims.internal.IImsServiceFeatureCallback;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telecom.ITelecomService;
@@ -4889,57 +4890,60 @@
         }
     }
 
-    /** @hide */
-    @IntDef({ImsFeature.EMERGENCY_MMTEL, ImsFeature.MMTEL, ImsFeature.RCS})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface Feature {}
-
     /**
-     * Returns the {@link IImsMMTelFeature} that corresponds to the given slot Id and MMTel
-     * feature or {@link null} if the service is not available. If an MMTelFeature is available, the
-     * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
-     * @param slotIndex The SIM slot that we are requesting the {@link IImsMMTelFeature} for.
-     * @param callback Listener that will send updates to ImsManager when there are updates to
-     * ImsServiceController.
-     * @return {@link IImsMMTelFeature} interface for the feature specified or {@code null} if
-     * it is unavailable.
+     * Enables IMS for the framework. This will trigger IMS registration and ImsFeature capability
+     * status updates, if not already enabled.
      * @hide
      */
-    public @Nullable IImsMMTelFeature getImsMMTelFeatureAndListen(int slotIndex,
-            IImsServiceFeatureCallback callback) {
+    public void enableIms(int slotId) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                return telephony.getMMTelFeatureAndListen(slotIndex, callback);
+                telephony.enableIms(slotId);
             }
         } catch (RemoteException e) {
-            Rlog.e(TAG, "getImsMMTelFeatureAndListen, RemoteException: "
+            Rlog.e(TAG, "enableIms, RemoteException: "
                     + e.getMessage());
         }
-        return null;
     }
 
     /**
-     * Returns the {@link IImsMMTelFeature} that corresponds to the given slot Id and MMTel
-     * feature for emergency calling or {@link null} if the service is not available. If an
-     * MMTelFeature is available, the {@link IImsServiceFeatureCallback} callback is registered as a
-     * listener for feature updates.
-     * @param slotIndex The SIM slot that we are requesting the {@link IImsMMTelFeature} for.
+     * Disables IMS for the framework. This will trigger IMS de-registration and trigger ImsFeature
+     * status updates to disabled.
+     * @hide
+     */
+    public void disableIms(int slotId) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.disableIms(slotId);
+            }
+        } catch (RemoteException e) {
+            Rlog.e(TAG, "disableIms, RemoteException: "
+                    + e.getMessage());
+        }
+    }
+
+    /**
+     * Returns the {@link IImsMmTelFeature} that corresponds to the given slot Id and MMTel
+     * feature or {@link null} if the service is not available. If an MMTelFeature is available, the
+     * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
+     * @param slotIndex The SIM slot that we are requesting the {@link IImsMmTelFeature} for.
      * @param callback Listener that will send updates to ImsManager when there are updates to
      * ImsServiceController.
-     * @return {@link IImsMMTelFeature} interface for the feature specified or {@code null} if
+     * @return {@link IImsMmTelFeature} interface for the feature specified or {@code null} if
      * it is unavailable.
      * @hide
      */
-    public @Nullable IImsMMTelFeature getImsEmergencyMMTelFeatureAndListen(int slotIndex,
+    public @Nullable IImsMmTelFeature getImsMmTelFeatureAndListen(int slotIndex,
             IImsServiceFeatureCallback callback) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                return telephony.getEmergencyMMTelFeatureAndListen(slotIndex, callback);
+                return telephony.getMmTelFeatureAndListen(slotIndex, callback);
             }
         } catch (RemoteException e) {
-            Rlog.e(TAG, "getImsEmergencyMMTelFeatureAndListen, RemoteException: "
+            Rlog.e(TAG, "getImsMmTelFeatureAndListen, RemoteException: "
                     + e.getMessage());
         }
         return null;
@@ -4991,6 +4995,25 @@
     }
 
     /**
+     * @return the {@IImsConfig} interface that corresponds with the slot index and feature.
+     * @param slotIndex The SIM slot corresponding to the ImsService ImsConfig is active for.
+     * @param feature An integer indicating the feature that we wish to get the ImsConfig for.
+     * Corresponds to features defined in ImsFeature.
+     * @hide
+     */
+    public @Nullable IImsConfig getImsConfig(int slotIndex, int feature) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getImsConfig(slotIndex, feature);
+            }
+        } catch (RemoteException e) {
+            Rlog.e(TAG, "getImsRegistration, RemoteException: " + e.getMessage());
+        }
+        return null;
+    }
+
+    /**
      * Set IMS registration state
      *
      * @param Registration state
diff --git a/telephony/java/com/android/ims/ImsCallForwardInfo.aidl b/telephony/java/android/telephony/ims/ImsCallForwardInfo.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsCallForwardInfo.aidl
rename to telephony/java/android/telephony/ims/ImsCallForwardInfo.aidl
index a7c3f9a..b322b39 100644
--- a/telephony/java/com/android/ims/ImsCallForwardInfo.aidl
+++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.ims;
+package android.telephony.ims;
 
 parcelable ImsCallForwardInfo;
diff --git a/telephony/java/com/android/ims/ImsCallForwardInfo.java b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
similarity index 77%
rename from telephony/java/com/android/ims/ImsCallForwardInfo.java
rename to telephony/java/android/telephony/ims/ImsCallForwardInfo.java
index eeee0fc..6d72181 100644
--- a/telephony/java/com/android/ims/ImsCallForwardInfo.java
+++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 The Android Open Source Project
+ * 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.
@@ -11,11 +11,12 @@
  * 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.
+ * limitations under the License
  */
 
-package com.android.ims;
+package android.telephony.ims;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -24,23 +25,32 @@
  *
  * @hide
  */
-public class ImsCallForwardInfo implements Parcelable {
+@SystemApi
+public final class ImsCallForwardInfo implements Parcelable {
     // Refer to ImsUtInterface#CDIV_CF_XXX
+    /** @hide */
     public int mCondition;
     // 0: disabled, 1: enabled
+    /** @hide */
     public int mStatus;
     // 0x91: International, 0x81: Unknown
+    /** @hide */
     public int mToA;
     // Service class
+    /** @hide */
     public int mServiceClass;
     // Number (it will not include the "sip" or "tel" URI scheme)
+    /** @hide */
     public String mNumber;
     // No reply timer for CF
+    /** @hide */
     public int mTimeSeconds;
 
+    /** @hide */
     public ImsCallForwardInfo() {
     }
 
+    /** @hide */
     public ImsCallForwardInfo(Parcel in) {
         readFromParcel(in);
     }
@@ -91,4 +101,28 @@
             return new ImsCallForwardInfo[size];
         }
     };
+
+    public int getCondition() {
+        return mCondition;
+    }
+
+    public int getStatus() {
+        return mStatus;
+    }
+
+    public int getToA() {
+        return mToA;
+    }
+
+    public int getServiceClass() {
+        return mServiceClass;
+    }
+
+    public String getNumber() {
+        return mNumber;
+    }
+
+    public int getTimeSeconds() {
+        return mTimeSeconds;
+    }
 }
diff --git a/telephony/java/com/android/ims/ImsCallProfile.aidl b/telephony/java/android/telephony/ims/ImsCallProfile.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsCallProfile.aidl
rename to telephony/java/android/telephony/ims/ImsCallProfile.aidl
index a356d13..e24e145 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.aidl
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.ims;
+package android.telephony.ims;
 
 parcelable ImsCallProfile;
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
similarity index 89%
rename from telephony/java/com/android/ims/ImsCallProfile.java
rename to telephony/java/android/telephony/ims/ImsCallProfile.java
index 693aaff..27e5f94 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 The Android Open Source Project
+ * 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.
@@ -11,11 +11,12 @@
  * 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.
+ * limitations under the License
  */
 
-package com.android.ims;
+package android.telephony.ims;
 
+import android.annotation.SystemApi;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -32,7 +33,8 @@
  *
  * @hide
  */
-public class ImsCallProfile implements Parcelable {
+@SystemApi
+public final class ImsCallProfile implements Parcelable {
     private static final String TAG = "ImsCallProfile";
 
     /**
@@ -110,52 +112,92 @@
      *      the video during voice call.
      *  conference_avail : Indicates if the session can be extended to the conference.
      */
+    /**
+     * @hide
+     */
     public static final String EXTRA_CONFERENCE = "conference";
+    /**
+     * @hide
+     */
     public static final String EXTRA_E_CALL = "e_call";
+    /**
+     * @hide
+     */
     public static final String EXTRA_VMS = "vms";
+    /**
+     * @hide
+     */
     public static final String EXTRA_CALL_MODE_CHANGEABLE = "call_mode_changeable";
+    /**
+     * @hide
+     */
     public static final String EXTRA_CONFERENCE_AVAIL = "conference_avail";
 
     // Extra string for internal use only. OEMs should not use
     // this for packing extras.
+    /**
+     * @hide
+     */
     public static final String EXTRA_OEM_EXTRAS = "OemCallExtras";
 
     /**
-     * Integer extra properties
-     *  oir : Rule for originating identity (number) presentation, MO/MT.
+     * Rule for originating identity (number) presentation, MO/MT.
      *      {@link ImsCallProfile#OIR_DEFAULT}
      *      {@link ImsCallProfile#OIR_PRESENTATION_RESTRICTED}
      *      {@link ImsCallProfile#OIR_PRESENTATION_NOT_RESTRICTED}
-     *  cnap : Rule for calling name presentation
+     */
+    public static final String EXTRA_OIR = "oir";
+    /**
+     * Rule for calling name presentation
      *      {@link ImsCallProfile#OIR_DEFAULT}
      *      {@link ImsCallProfile#OIR_PRESENTATION_RESTRICTED}
      *      {@link ImsCallProfile#OIR_PRESENTATION_NOT_RESTRICTED}
-     *  dialstring : To identify the Ims call type, MO
-     *      {@link ImsCallProfile#DIALSTRING_NORMAL_CALL}
+     */
+    public static final String EXTRA_CNAP = "cnap";
+    /**
+     * To identify the Ims call type, MO
+     *      {@link ImsCallProfile#DIALSTRING_NORMAL}
      *      {@link ImsCallProfile#DIALSTRING_SS_CONF}
      *      {@link ImsCallProfile#DIALSTRING_USSD}
      */
-    public static final String EXTRA_OIR = "oir";
-    public static final String EXTRA_CNAP = "cnap";
     public static final String EXTRA_DIALSTRING = "dialstring";
 
     /**
      * Values for EXTRA_OIR / EXTRA_CNAP
      */
+    /**
+     * Default presentation for Originating Identity.
+     */
     public static final int OIR_DEFAULT = 0;    // "user subscription default value"
+    /**
+     * Restricted presentation for Originating Identity.
+     */
     public static final int OIR_PRESENTATION_RESTRICTED = 1;
+    /**
+     * Not restricted presentation for Originating Identity.
+     */
     public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2;
+    /**
+     * Presentation unknown for Originating Identity.
+     */
     public static final int OIR_PRESENTATION_UNKNOWN = 3;
+    /**
+     * Payphone presentation for Originating Identity.
+     */
     public static final int OIR_PRESENTATION_PAYPHONE = 4;
 
+    //Values for EXTRA_DIALSTRING
     /**
-     * Values for EXTRA_DIALSTRING
+     * A default or normal normal call.
      */
-    // default (normal call)
     public static final int DIALSTRING_NORMAL = 0;
-    // Call for SIP-based user configuration
+    /**
+     * Call for SIP-based user configuration
+     */
     public static final int DIALSTRING_SS_CONF = 1;
-    // Call for USSD message
+    /**
+     * Call for USSD message
+     */
     public static final int DIALSTRING_USSD = 2;
 
     /**
@@ -215,8 +257,11 @@
      */
     public static final String EXTRA_CALL_RAT_TYPE_ALT = "callRadioTech";
 
+    /** @hide */
     public int mServiceType;
+    /** @hide */
     public int mCallType;
+    /** @hide */
     public int mRestrictCause = CALL_RESTRICT_CAUSE_NONE;
 
     /**
@@ -241,13 +286,17 @@
      * Invalid types will be removed when the {@link ImsCallProfile} is parceled for transmit across
      * a {@link android.os.Binder}.
      */
+    /** @hide */
     public Bundle mCallExtras;
+    /** @hide */
     public ImsStreamMediaProfile mMediaProfile;
 
+    /** @hide */
     public ImsCallProfile(Parcel in) {
         readFromParcel(in);
     }
 
+    /** @hide */
     public ImsCallProfile() {
         mServiceType = SERVICE_TYPE_NORMAL;
         mCallType = CALL_TYPE_VOICE_N_VIDEO;
@@ -255,6 +304,7 @@
         mMediaProfile = new ImsStreamMediaProfile();
     }
 
+    /** @hide */
     public ImsCallProfile(int serviceType, int callType) {
         mServiceType = serviceType;
         mCallType = callType;
@@ -366,8 +416,28 @@
         }
     };
 
+    public int getServiceType() {
+        return mServiceType;
+    }
+
+    public int getCallType() {
+        return mCallType;
+    }
+
+    public int getRestrictCause() {
+        return mRestrictCause;
+    }
+
+    public Bundle getCallExtras() {
+        return mCallExtras;
+    }
+
+    public ImsStreamMediaProfile getMediaProfile() {
+        return mMediaProfile;
+    }
+
     /**
-     * Converts from the call types defined in {@link com.android.ims.ImsCallProfile} to the
+     * Converts from the call types defined in {@link ImsCallProfile} to the
      * video state values defined in {@link VideoProfile}.
      *
      * @param callProfile The call profile.
@@ -434,9 +504,9 @@
     }
 
     /**
-     * Translate presentation value to OIR value
-     * @param presentation
-     * @return OIR valuse
+     * Badly named old method, kept for compatibility.
+     * See {@link #presentationToOir(int)}.
+     * @hide
      */
     public static int presentationToOIR(int presentation) {
         switch (presentation) {
@@ -454,9 +524,19 @@
     }
 
     /**
+     * Translate presentation value to OIR value
+     * @param presentation
+     * @return OIR values
+     */
+    public static int presentationToOir(int presentation) {
+        return presentationToOIR(presentation);
+    }
+
+    /**
      * Translate OIR value to presentation value
      * @param oir value
      * @return presentation value
+     * @hide
      */
     public static int OIRToPresentation(int oir) {
         switch(oir) {
diff --git a/telephony/java/com/android/ims/internal/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
similarity index 90%
rename from telephony/java/com/android/ims/internal/ImsCallSession.java
rename to telephony/java/android/telephony/ims/ImsCallSession.java
index 1736b80..207965d 100644
--- a/telephony/java/com/android/ims/internal/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 The Android Open Source Project
+ * 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.
@@ -11,23 +11,25 @@
  * 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.
+ * limitations under the License
  */
 
-package com.android.ims.internal;
+package android.telephony.ims;
 
+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.ImsCallSessionListenerImplBase;
+import android.telephony.ims.stub.ImsCallSessionImplBase;
 import android.util.Log;
-import com.android.ims.ImsCallProfile;
-import com.android.ims.ImsConferenceState;
-import com.android.ims.ImsReasonInfo;
-import com.android.ims.ImsStreamMediaProfile;
-import com.android.ims.ImsSuppServiceNotification;
+
+import com.android.ims.internal.IImsCallSession;
+import com.android.ims.internal.IImsVideoCallProvider;
 
 /**
  * Provides the call initiation/termination, and media exchange between two IMS endpoints.
@@ -39,7 +41,8 @@
     private static final String TAG = "ImsCallSession";
 
     /**
-     * Defines IMS call session state.
+     * 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;
@@ -92,6 +95,7 @@
      * 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 {
         /**
@@ -449,6 +453,7 @@
     private boolean mClosed = false;
     private Listener mListener;
 
+    /** @hide */
     public ImsCallSession(IImsCallSession iSession) {
         miSession = iSession;
 
@@ -462,6 +467,7 @@
         }
     }
 
+    /** @hide */
     public ImsCallSession(IImsCallSession iSession, Listener listener) {
         this(iSession);
         setListener(listener);
@@ -470,15 +476,17 @@
     /**
      * Closes this object. This object is not usable after being closed.
      */
-    public synchronized void close() {
-        if (mClosed) {
-            return;
-        }
+    public void close() {
+        synchronized (this) {
+            if (mClosed) {
+                return;
+            }
 
-        try {
-            miSession.close();
-            mClosed = true;
-        } catch (RemoteException e) {
+            try {
+                miSession.close();
+                mClosed = true;
+            } catch (RemoteException e) {
+            }
         }
     }
 
@@ -554,6 +562,7 @@
      * Gets the video call provider for the session.
      *
      * @return The video call provider.
+     * @hide
      */
     public IImsVideoCallProvider getVideoCallProvider() {
         if (mClosed) {
@@ -659,6 +668,7 @@
      * override the previous listener.
      *
      * @param listener to listen to the session events of this object
+     * @hide
      */
     public void setListener(Listener listener) {
         mListener = listener;
@@ -987,7 +997,6 @@
      * Sends Rtt Message
      *
      * @param rttMessage rtt text to be sent
-     * @throws ImsException if call is absent
      */
     public void sendRttMessage(String rttMessage) {
         if (mClosed) {
@@ -1004,7 +1013,6 @@
      * Sends RTT Upgrade request
      *
      * @param to   : expected profile
-     * @throws CallStateException
      */
     public void sendRttModifyRequest(ImsCallProfile to) {
         if (mClosed) {
@@ -1021,7 +1029,6 @@
      * Sends RTT Upgrade response
      *
      * @param response : response for upgrade
-     * @throws CallStateException
      */
     public void sendRttModifyResponse(boolean response) {
         if (mClosed) {
@@ -1040,37 +1047,33 @@
      * the application is notified by having one of the methods called on
      * the {@link IImsCallSessionListener}.
      */
-    private class IImsCallSessionListenerProxy extends ImsCallSessionListenerImplBase {
+    private class IImsCallSessionListenerProxy extends IImsCallSessionListener.Stub {
         /**
          * Notifies the result of the basic session operation (setup / terminate).
          */
         @Override
-        public void callSessionProgressing(IImsCallSession session,
-                ImsStreamMediaProfile profile) {
+        public void callSessionProgressing(ImsStreamMediaProfile profile) {
             if (mListener != null) {
                 mListener.callSessionProgressing(ImsCallSession.this, profile);
             }
         }
 
         @Override
-        public void callSessionStarted(IImsCallSession session,
-                ImsCallProfile profile) {
+        public void callSessionInitiated(ImsCallProfile profile) {
             if (mListener != null) {
                 mListener.callSessionStarted(ImsCallSession.this, profile);
             }
         }
 
         @Override
-        public void callSessionStartFailed(IImsCallSession session,
-                ImsReasonInfo reasonInfo) {
+        public void callSessionInitiatedFailed(ImsReasonInfo reasonInfo) {
             if (mListener != null) {
                 mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
             }
         }
 
         @Override
-        public void callSessionTerminated(IImsCallSession session,
-                ImsReasonInfo reasonInfo) {
+        public void callSessionTerminated(ImsReasonInfo reasonInfo) {
             if (mListener != null) {
                 mListener.callSessionTerminated(ImsCallSession.this, reasonInfo);
             }
@@ -1080,48 +1083,42 @@
          * Notifies the result of the call hold/resume operation.
          */
         @Override
-        public void callSessionHeld(IImsCallSession session,
-                ImsCallProfile profile) {
+        public void callSessionHeld(ImsCallProfile profile) {
             if (mListener != null) {
                 mListener.callSessionHeld(ImsCallSession.this, profile);
             }
         }
 
         @Override
-        public void callSessionHoldFailed(IImsCallSession session,
-                ImsReasonInfo reasonInfo) {
+        public void callSessionHoldFailed(ImsReasonInfo reasonInfo) {
             if (mListener != null) {
                 mListener.callSessionHoldFailed(ImsCallSession.this, reasonInfo);
             }
         }
 
         @Override
-        public void callSessionHoldReceived(IImsCallSession session,
-                ImsCallProfile profile) {
+        public void callSessionHoldReceived(ImsCallProfile profile) {
             if (mListener != null) {
                 mListener.callSessionHoldReceived(ImsCallSession.this, profile);
             }
         }
 
         @Override
-        public void callSessionResumed(IImsCallSession session,
-                ImsCallProfile profile) {
+        public void callSessionResumed(ImsCallProfile profile) {
             if (mListener != null) {
                 mListener.callSessionResumed(ImsCallSession.this, profile);
             }
         }
 
         @Override
-        public void callSessionResumeFailed(IImsCallSession session,
-                ImsReasonInfo reasonInfo) {
+        public void callSessionResumeFailed(ImsReasonInfo reasonInfo) {
             if (mListener != null) {
                 mListener.callSessionResumeFailed(ImsCallSession.this, reasonInfo);
             }
         }
 
         @Override
-        public void callSessionResumeReceived(IImsCallSession session,
-                ImsCallProfile profile) {
+        public void callSessionResumeReceived(ImsCallProfile profile) {
             if (mListener != null) {
                 mListener.callSessionResumeReceived(ImsCallSession.this, profile);
             }
@@ -1130,13 +1127,11 @@
         /**
          * Notifies the start of a call merge operation.
          *
-         * @param session The call session.
          * @param newSession The merged call session.
          * @param profile The call profile.
          */
         @Override
-        public void callSessionMergeStarted(IImsCallSession session,
-                IImsCallSession newSession, ImsCallProfile profile) {
+        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");
@@ -1173,12 +1168,10 @@
         /**
          * Notifies of a failure to perform a call merge operation.
          *
-         * @param session The call session.
          * @param reasonInfo The merge failure reason.
          */
         @Override
-        public void callSessionMergeFailed(IImsCallSession session,
-                ImsReasonInfo reasonInfo) {
+        public void callSessionMergeFailed(ImsReasonInfo reasonInfo) {
             if (mListener != null) {
                 mListener.callSessionMergeFailed(ImsCallSession.this, reasonInfo);
             }
@@ -1188,24 +1181,21 @@
          * Notifies the result of call upgrade / downgrade or any other call updates.
          */
         @Override
-        public void callSessionUpdated(IImsCallSession session,
-                ImsCallProfile profile) {
+        public void callSessionUpdated(ImsCallProfile profile) {
             if (mListener != null) {
                 mListener.callSessionUpdated(ImsCallSession.this, profile);
             }
         }
 
         @Override
-        public void callSessionUpdateFailed(IImsCallSession session,
-                ImsReasonInfo reasonInfo) {
+        public void callSessionUpdateFailed(ImsReasonInfo reasonInfo) {
             if (mListener != null) {
                 mListener.callSessionUpdateFailed(ImsCallSession.this, reasonInfo);
             }
         }
 
         @Override
-        public void callSessionUpdateReceived(IImsCallSession session,
-                ImsCallProfile profile) {
+        public void callSessionUpdateReceived(ImsCallProfile profile) {
             if (mListener != null) {
                 mListener.callSessionUpdateReceived(ImsCallSession.this, profile);
             }
@@ -1215,8 +1205,8 @@
          * Notifies the result of conference extension.
          */
         @Override
-        public void callSessionConferenceExtended(IImsCallSession session,
-                IImsCallSession newSession, ImsCallProfile profile) {
+        public void callSessionConferenceExtended(IImsCallSession newSession,
+                ImsCallProfile profile) {
             if (mListener != null) {
                 mListener.callSessionConferenceExtended(ImsCallSession.this,
                         new ImsCallSession(newSession), profile);
@@ -1224,16 +1214,15 @@
         }
 
         @Override
-        public void callSessionConferenceExtendFailed(IImsCallSession session,
-                ImsReasonInfo reasonInfo) {
+        public void callSessionConferenceExtendFailed(ImsReasonInfo reasonInfo) {
             if (mListener != null) {
                 mListener.callSessionConferenceExtendFailed(ImsCallSession.this, reasonInfo);
             }
         }
 
         @Override
-        public void callSessionConferenceExtendReceived(IImsCallSession session,
-                IImsCallSession newSession, ImsCallProfile profile) {
+        public void callSessionConferenceExtendReceived(IImsCallSession newSession,
+                ImsCallProfile profile) {
             if (mListener != null) {
                 mListener.callSessionConferenceExtendReceived(ImsCallSession.this,
                         new ImsCallSession(newSession), profile);
@@ -1245,15 +1234,14 @@
          * the conference session.
          */
         @Override
-        public void callSessionInviteParticipantsRequestDelivered(IImsCallSession session) {
+        public void callSessionInviteParticipantsRequestDelivered() {
             if (mListener != null) {
                 mListener.callSessionInviteParticipantsRequestDelivered(ImsCallSession.this);
             }
         }
 
         @Override
-        public void callSessionInviteParticipantsRequestFailed(IImsCallSession session,
-                ImsReasonInfo reasonInfo) {
+        public void callSessionInviteParticipantsRequestFailed(ImsReasonInfo reasonInfo) {
             if (mListener != null) {
                 mListener.callSessionInviteParticipantsRequestFailed(ImsCallSession.this,
                         reasonInfo);
@@ -1261,15 +1249,14 @@
         }
 
         @Override
-        public void callSessionRemoveParticipantsRequestDelivered(IImsCallSession session) {
+        public void callSessionRemoveParticipantsRequestDelivered() {
             if (mListener != null) {
                 mListener.callSessionRemoveParticipantsRequestDelivered(ImsCallSession.this);
             }
         }
 
         @Override
-        public void callSessionRemoveParticipantsRequestFailed(IImsCallSession session,
-                ImsReasonInfo reasonInfo) {
+        public void callSessionRemoveParticipantsRequestFailed(ImsReasonInfo reasonInfo) {
             if (mListener != null) {
                 mListener.callSessionRemoveParticipantsRequestFailed(ImsCallSession.this,
                         reasonInfo);
@@ -1280,8 +1267,7 @@
          * Notifies the changes of the conference info. in the conference session.
          */
         @Override
-        public void callSessionConferenceStateUpdated(IImsCallSession session,
-                ImsConferenceState state) {
+        public void callSessionConferenceStateUpdated(ImsConferenceState state) {
             if (mListener != null) {
                 mListener.callSessionConferenceStateUpdated(ImsCallSession.this, state);
             }
@@ -1291,17 +1277,15 @@
          * Notifies the incoming USSD message.
          */
         @Override
-        public void callSessionUssdMessageReceived(IImsCallSession session,
-                int mode, String ussdMessage) {
+        public void callSessionUssdMessageReceived(int mode, String ussdMessage) {
             if (mListener != null) {
                 mListener.callSessionUssdMessageReceived(ImsCallSession.this, mode, ussdMessage);
             }
         }
 
         /**
-         * Notifies of a case where a {@link com.android.ims.internal.ImsCallSession} may
+         * Notifies of a case where a {@link ImsCallSession} may
          * potentially handover from one radio technology to another.
-         * @param session
          * @param srcAccessTech The source radio access technology; one of the access technology
          *                      constants defined in {@link android.telephony.ServiceState}.  For
          *                      example
@@ -1312,8 +1296,7 @@
          *                      {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}.
          */
         @Override
-        public void callSessionMayHandover(IImsCallSession session,
-                int srcAccessTech, int targetAccessTech) {
+        public void callSessionMayHandover(int srcAccessTech, int targetAccessTech) {
             if (mListener != null) {
                 mListener.callSessionMayHandover(ImsCallSession.this, srcAccessTech,
                         targetAccessTech);
@@ -1324,9 +1307,8 @@
          * Notifies of handover information for this call
          */
         @Override
-        public void callSessionHandover(IImsCallSession session,
-                                 int srcAccessTech, int targetAccessTech,
-                                 ImsReasonInfo reasonInfo) {
+        public void callSessionHandover(int srcAccessTech, int targetAccessTech,
+                ImsReasonInfo reasonInfo) {
             if (mListener != null) {
                 mListener.callSessionHandover(ImsCallSession.this, srcAccessTech,
                         targetAccessTech, reasonInfo);
@@ -1337,9 +1319,8 @@
          * Notifies of handover failure info for this call
          */
         @Override
-        public void callSessionHandoverFailed(IImsCallSession session,
-                                       int srcAccessTech, int targetAccessTech,
-                                       ImsReasonInfo reasonInfo) {
+        public void callSessionHandoverFailed(int srcAccessTech, int targetAccessTech,
+                ImsReasonInfo reasonInfo) {
             if (mListener != null) {
                 mListener.callSessionHandoverFailed(ImsCallSession.this, srcAccessTech,
                         targetAccessTech, reasonInfo);
@@ -1350,8 +1331,7 @@
          * Notifies the TTY mode received from remote party.
          */
         @Override
-        public void callSessionTtyModeReceived(IImsCallSession session,
-                int mode) {
+        public void callSessionTtyModeReceived(int mode) {
             if (mListener != null) {
                 mListener.callSessionTtyModeReceived(ImsCallSession.this, mode);
             }
@@ -1360,21 +1340,17 @@
         /**
          * 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(IImsCallSession session,
-                boolean isMultiParty) {
-
+        public void callSessionMultipartyStateChanged(boolean isMultiParty) {
             if (mListener != null) {
                 mListener.callSessionMultipartyStateChanged(ImsCallSession.this, isMultiParty);
             }
         }
 
         @Override
-        public void callSessionSuppServiceReceived(IImsCallSession session,
-                ImsSuppServiceNotification suppServiceInfo ) {
+        public void callSessionSuppServiceReceived(ImsSuppServiceNotification suppServiceInfo ) {
             if (mListener != null) {
                 mListener.callSessionSuppServiceReceived(ImsCallSession.this, suppServiceInfo);
             }
@@ -1384,8 +1360,7 @@
          * Received RTT modify request from remote party
          */
         @Override
-        public void callSessionRttModifyRequestReceived(IImsCallSession session,
-                ImsCallProfile callProfile) {
+        public void callSessionRttModifyRequestReceived(ImsCallProfile callProfile) {
             if (mListener != null) {
                 mListener.callSessionRttModifyRequestReceived(ImsCallSession.this, callProfile);
             }
diff --git a/telephony/java/android/telephony/ims/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
new file mode 100644
index 0000000..a7f124a
--- /dev/null
+++ b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
@@ -0,0 +1,603 @@
+/*
+ * 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.SystemApi;
+import android.os.RemoteException;
+import android.telephony.ims.aidl.IImsCallSessionListener;
+import android.telephony.ims.stub.ImsCallSessionImplBase;
+
+import com.android.ims.internal.IImsCallSession;
+
+/**
+ * Listener interface for notifying the Framework's {@link ImsCallSession} for updates to an ongoing
+ * IMS call.
+ *
+ * @hide
+ */
+// DO NOT remove or change the existing APIs, only add new ones to this implementation or you
+// will break other implementations of ImsCallSessionListener maintained by other ImsServices.
+// TODO: APIs in here do not conform to API guidelines yet. This can be changed if
+// ImsCallSessionListenerConverter is also changed.
+@SystemApi
+public class ImsCallSessionListener {
+
+    private final IImsCallSessionListener mListener;
+
+    /** @hide */
+    public ImsCallSessionListener(IImsCallSessionListener l) {
+        mListener = l;
+    }
+
+    /**
+     * A request has been sent out to initiate a new IMS call session and a 1xx response has been
+     * received from the network.
+     */
+    public void callSessionProgressing(ImsStreamMediaProfile profile) {
+        try {
+            mListener.callSessionProgressing(profile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session has been initiated.
+     *
+     * @param profile the associated {@link ImsCallProfile}.
+     */
+    public void callSessionInitiated(ImsCallProfile profile) {
+        try {
+            mListener.callSessionInitiated(profile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session establishment has failed.
+     *
+     * @param reasonInfo {@link ImsReasonInfo} detailing the reason of the IMS call session
+     * establishment failure.
+     */
+    public void callSessionInitiatedFailed(ImsReasonInfo reasonInfo) {
+        try {
+            mListener.callSessionInitiatedFailed(reasonInfo);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session has been terminated.
+     *
+     * @param reasonInfo {@link ImsReasonInfo} detailing the reason of the session termination.
+     */
+    public void callSessionTerminated(ImsReasonInfo reasonInfo) {
+        try {
+            mListener.callSessionTerminated(reasonInfo);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session has started the process of holding the call. If it fails,
+     * {@link #callSessionHoldFailed(ImsReasonInfo)} should be called.
+     *
+     * If the IMS call session is resumed, call {@link #callSessionResumed(ImsCallProfile)}.
+     *
+     * @param profile The associated {@link ImsCallProfile} of the call session that has been put
+     * on hold.
+     */
+    public void callSessionHeld(ImsCallProfile profile) {
+        try {
+            mListener.callSessionHeld(profile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session has failed to be held.
+     *
+     * @param reasonInfo {@link ImsReasonInfo} detailing the reason of the session hold failure.
+     */
+    public void callSessionHoldFailed(ImsReasonInfo reasonInfo) {
+        try {
+            mListener.callSessionHoldFailed(reasonInfo);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * This IMS Call session has been put on hold by the remote party.
+     *
+     * @param profile The {@link ImsCallProfile} associated with this IMS call session.
+     */
+    public void callSessionHoldReceived(ImsCallProfile profile) {
+        try {
+            mListener.callSessionHoldReceived(profile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session has started the process of resuming the call. If the process of resuming
+     * the call fails, call {@link #callSessionResumeFailed(ImsReasonInfo)}.
+     *
+     * @param profile The {@link ImsCallProfile} associated with this IMS call session.
+     */
+    public void callSessionResumed(ImsCallProfile profile) {
+        try {
+            mListener.callSessionResumed(profile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session resume has failed.
+     *
+     * @param reasonInfo {@link ImsReasonInfo} containing the detailed reason of the session resume
+     * failure.
+     */
+    public void callSessionResumeFailed(ImsReasonInfo reasonInfo) {
+        try {
+            mListener.callSessionResumeFailed(reasonInfo);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The remote party has resumed this IMS call session.
+     *
+     * @param profile {@link ImsCallProfile} associated with the IMS call session.
+     */
+    public void callSessionResumeReceived(ImsCallProfile profile) {
+        try {
+            mListener.callSessionResumeReceived(profile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session merge has been started.  At this point, the {@code newSession}
+     * represents the IMS call session which represents the new merged conference and has been
+     * initiated to the IMS conference server.
+     *
+     * @param newSession the {@link ImsCallSessionImplBase} that represents the merged active & held
+     * sessions.
+     * @param profile The {@link ImsCallProfile} associated with this IMS call session.
+     */
+    public void callSessionMergeStarted(ImsCallSessionImplBase newSession, ImsCallProfile profile)
+    {
+        try {
+            mListener.callSessionMergeStarted(newSession != null ?
+                            newSession.getServiceImpl() : null, profile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Compatibility method for older implementations.
+     * See {@link #callSessionMergeStarted(ImsCallSessionImplBase, ImsCallProfile)}.
+     *
+     * @hide
+     */
+    public void callSessionMergeStarted(IImsCallSession newSession, ImsCallProfile profile)
+    {
+        try {
+            mListener.callSessionMergeStarted(newSession, profile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The session merge is successful and the merged {@link ImsCallSession} is active.
+     *
+     * @param newSession the new {@link ImsCallSessionImplBase}
+     *                  that represents the conference IMS call
+     * session.
+     */
+    public void callSessionMergeComplete(ImsCallSessionImplBase newSession) {
+        try {
+            mListener.callSessionMergeComplete(newSession != null ?
+                    newSession.getServiceImpl() : null);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Compatibility method for older implementations of ImsService.
+     *
+     * See {@link #callSessionMergeComplete(ImsCallSessionImplBase)}}.
+     *
+     * @hide
+     */
+    public void callSessionMergeComplete(IImsCallSession newSession) {
+        try {
+            mListener.callSessionMergeComplete(newSession);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session merge has failed.
+     *
+     * @param reasonInfo {@link ImsReasonInfo} contining the reason for the call merge failure.
+     */
+    public void callSessionMergeFailed(ImsReasonInfo reasonInfo) {
+        try {
+            mListener.callSessionMergeFailed(reasonInfo);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session profile has been updated. Does not include holding or resuming a call.
+     *
+     * @param profile The {@link ImsCallProfile} associated with the updated IMS call session.
+     */
+    public void callSessionUpdated(ImsCallProfile profile) {
+        try {
+            mListener.callSessionUpdated(profile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session profile update has failed.
+     *
+     * @param reasonInfo {@link ImsReasonInfo} containing a reason for the session update failure.
+     */
+    public void callSessionUpdateFailed(ImsReasonInfo reasonInfo) {
+        try {
+            mListener.callSessionUpdateFailed(reasonInfo);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session profile has received an update from the remote user.
+     *
+     * @param profile The new {@link ImsCallProfile} associated with the update.
+     */
+    public void callSessionUpdateReceived(ImsCallProfile profile) {
+        try {
+            mListener.callSessionUpdateReceived(profile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Called when the session has been extended to a conference session.
+     *
+     * If the conference extension fails, call
+     * {@link #callSessionConferenceExtendFailed(ImsReasonInfo)}.
+     *
+     * @param newSession the session object that is extended to the conference from the active
+     * IMS Call session.
+     * @param profile The {@link ImsCallProfile} associated with the IMS call session.
+     */
+    public void callSessionConferenceExtended(ImsCallSessionImplBase newSession,
+            ImsCallProfile profile) {
+        try {
+            mListener.callSessionConferenceExtended(
+                    newSession != null ? newSession.getServiceImpl() : null, profile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Compatibility method to interface with older versions of ImsService.
+     * See {@link #callSessionConferenceExtended(ImsCallSessionImplBase, ImsCallProfile)}.
+     *
+     * @hide
+     */
+    public void callSessionConferenceExtended(IImsCallSession newSession, ImsCallProfile profile) {
+        try {
+            mListener.callSessionConferenceExtended(newSession, profile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The previous conference extension has failed.
+     *
+     * @param reasonInfo {@link ImsReasonInfo} containing the detailed reason of the conference
+     * extension failure.
+     */
+    public void callSessionConferenceExtendFailed(ImsReasonInfo reasonInfo) {
+        try {
+            mListener.callSessionConferenceExtendFailed(reasonInfo);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * A conference extension has been received received from the remote party.
+     *
+     * @param newSession An {@link ImsCallSessionImplBase}
+     *                   representing the extended IMS call session.
+     * @param profile The {@link ImsCallProfile} associated with the new IMS call session.
+     */
+    public void callSessionConferenceExtendReceived(ImsCallSessionImplBase newSession,
+            ImsCallProfile profile) {
+        try {
+            mListener.callSessionConferenceExtendReceived(newSession != null
+                    ? newSession.getServiceImpl() : null, profile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Compatibility method to interface with older versions of ImsService.
+     * See {@link #callSessionConferenceExtendReceived(ImsCallSessionImplBase, ImsCallProfile)}.
+     *
+     * @hide
+     */
+    public void callSessionConferenceExtendReceived(IImsCallSession newSession,
+            ImsCallProfile profile) {
+        try {
+            mListener.callSessionConferenceExtendReceived(newSession, profile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The request to invite participants to the conference has been delivered to the conference
+     * server.
+     */
+    public void callSessionInviteParticipantsRequestDelivered() {
+        try {
+            mListener.callSessionInviteParticipantsRequestDelivered();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The previous request to invite participants to the conference (see
+     * {@link #callSessionInviteParticipantsRequestDelivered()}) has failed.
+     *
+     * @param reasonInfo {@link ImsReasonInfo} detailing the reason forthe conference invitation
+     * failure.
+     */
+    public void callSessionInviteParticipantsRequestFailed(ImsReasonInfo reasonInfo)
+    {
+        try {
+            mListener.callSessionInviteParticipantsRequestFailed(reasonInfo);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The request to remove participants from the conference has been delivered to the conference
+     * server.
+     */
+    public void callSessionRemoveParticipantsRequestDelivered() {
+        try {
+            mListener.callSessionRemoveParticipantsRequestDelivered();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The previous request to remove participants from the conference (see
+     * {@link #callSessionRemoveParticipantsRequestDelivered()}) has failed.
+     *
+     * @param reasonInfo {@link ImsReasonInfo} detailing the reason for the conference removal
+     * failure.
+     */
+    public void callSessionRemoveParticipantsRequestFailed(ImsReasonInfo reasonInfo)
+    {
+        try {
+            mListener.callSessionInviteParticipantsRequestFailed(reasonInfo);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session's conference state has changed.
+     *
+     * @param state The new {@link ImsConferenceState} associated with the conference.
+     */
+    public void callSessionConferenceStateUpdated(ImsConferenceState state) {
+        try {
+            mListener.callSessionConferenceStateUpdated(state);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session has received a Ussd message.
+     *
+     * @param mode The mode of the USSD message, either
+     * {@link ImsCallSessionImplBase#USSD_MODE_NOTIFY} or
+     * {@link ImsCallSessionImplBase#USSD_MODE_REQUEST}.
+     * @param ussdMessage The USSD message.
+     */
+    public void callSessionUssdMessageReceived(int mode, String ussdMessage)
+    {
+        try {
+            mListener.callSessionUssdMessageReceived(mode, ussdMessage);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * An {@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}.
+     */
+    public void callSessionMayHandover(int srcAccessTech, int targetAccessTech)
+    {
+        try {
+            mListener.callSessionMayHandover(srcAccessTech, targetAccessTech);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session's access technology has changed.
+     *
+     * @param srcAccessTech original access technology, defined in
+     * {@link android.telephony.ServiceState}.
+     * @param targetAccessTech new access technology, defined in
+     * {@link android.telephony.ServiceState}.
+     * @param reasonInfo The {@link ImsReasonInfo} associated with this handover.
+     */
+    public void callSessionHandover(int srcAccessTech, int targetAccessTech,
+            ImsReasonInfo reasonInfo) {
+        try {
+            mListener.callSessionHandover(srcAccessTech, targetAccessTech, reasonInfo);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The IMS call session's access technology change has failed..
+     *
+     * @param srcAccessTech original access technology
+     * @param targetAccessTech new access technology
+     * @param reasonInfo An {@link ImsReasonInfo} detailing the reason for the failure.
+     */
+    public void callSessionHandoverFailed(int srcAccessTech, int targetAccessTech,
+            ImsReasonInfo reasonInfo) {
+        try {
+            mListener.callSessionHandoverFailed(srcAccessTech, targetAccessTech, reasonInfo);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The TTY mode has been changed by the remote party.
+     *
+     * @param mode one of the following: -
+     *             {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} -
+     *             {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} -
+     *             {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} -
+     *             {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
+     */
+    public void callSessionTtyModeReceived(int mode) {
+        try {
+            mListener.callSessionTtyModeReceived(mode);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * The multiparty state has been changed for this {@code ImsCallSession}.
+     *
+     * @param isMultiParty {@code true} if the session became multiparty, {@code false} otherwise.
+     */
+    public void callSessionMultipartyStateChanged(boolean isMultiParty) {
+        try {
+            mListener.callSessionMultipartyStateChanged(isMultiParty);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Supplementary service information has been received for the current IMS call session.
+     *
+     * @param suppSrvNotification The {@link ImsSuppServiceNotification} containing the change.
+     */
+    public void callSessionSuppServiceReceived(ImsSuppServiceNotification suppSrvNotification)
+    {
+        try {
+            mListener.callSessionSuppServiceReceived(suppSrvNotification);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * An RTT modify request has been received from the remote party.
+     *
+     * @param callProfile An {@link ImsCallProfile} with the updated attributes
+     */
+    public void callSessionRttModifyRequestReceived(ImsCallProfile callProfile)
+    {
+        try {
+            mListener.callSessionRttModifyRequestReceived(callProfile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * An RTT modify response has been received.
+     *
+     * @param status the received response for RTT modify request.
+     */
+    public void callSessionRttModifyResponseReceived(int status) {
+        try {
+            mListener.callSessionRttModifyResponseReceived(status);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * An RTT message has been received from the remote party.
+     *
+     * @param rttMessage The RTT message that has been received.
+     */
+    public void callSessionRttMessageReceived(String rttMessage) {
+        try {
+            mListener.callSessionRttMessageReceived(rttMessage);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
+
diff --git a/telephony/java/com/android/ims/ImsConferenceState.aidl b/telephony/java/android/telephony/ims/ImsConferenceState.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsConferenceState.aidl
rename to telephony/java/android/telephony/ims/ImsConferenceState.aidl
index 2fc029f..e2b371c 100644
--- a/telephony/java/com/android/ims/ImsConferenceState.aidl
+++ b/telephony/java/android/telephony/ims/ImsConferenceState.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.ims;
+package android.telephony.ims;
 
 parcelable ImsConferenceState;
diff --git a/telephony/java/com/android/ims/ImsConferenceState.java b/telephony/java/android/telephony/ims/ImsConferenceState.java
similarity index 95%
rename from telephony/java/com/android/ims/ImsConferenceState.java
rename to telephony/java/android/telephony/ims/ImsConferenceState.java
index 0afde88..66d2f8d 100644
--- a/telephony/java/com/android/ims/ImsConferenceState.java
+++ b/telephony/java/android/telephony/ims/ImsConferenceState.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 The Android Open Source Project
+ * 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.
@@ -11,16 +11,17 @@
  * 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.
+ * limitations under the License
  */
 
-package com.android.ims;
+package android.telephony.ims;
 
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map.Entry;
 import java.util.Set;
 
+import android.annotation.SystemApi;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -32,7 +33,8 @@
  *
  * @hide
  */
-public class ImsConferenceState implements Parcelable {
+@SystemApi
+public final class ImsConferenceState implements Parcelable {
     /**
      * conference-info : user
      */
@@ -87,12 +89,13 @@
      */
     public static final String SIP_STATUS_CODE = "sipstatuscode";
 
-    public HashMap<String, Bundle> mParticipants = new HashMap<String, Bundle>();
+    public final HashMap<String, Bundle> mParticipants = new HashMap<String, Bundle>();
 
+    /** @hide */
     public ImsConferenceState() {
     }
 
-    public ImsConferenceState(Parcel in) {
+    private ImsConferenceState(Parcel in) {
         readFromParcel(in);
     }
 
diff --git a/telephony/java/com/android/ims/ImsExternalCallState.aidl b/telephony/java/android/telephony/ims/ImsExternalCallState.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsExternalCallState.aidl
rename to telephony/java/android/telephony/ims/ImsExternalCallState.aidl
index c208702..99d2935 100644
--- a/telephony/java/com/android/ims/ImsExternalCallState.aidl
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.ims;
+package android.telephony.ims;
 
 parcelable ImsExternalCallState;
diff --git a/telephony/java/com/android/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java
similarity index 92%
rename from telephony/java/com/android/ims/ImsExternalCallState.java
rename to telephony/java/android/telephony/ims/ImsExternalCallState.java
index da26073..e82c115 100644
--- a/telephony/java/com/android/ims/ImsExternalCallState.java
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 The Android Open Source Project
+ * 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.
@@ -11,11 +11,12 @@
  * 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.
+ * limitations under the License
  */
 
-package com.android.ims;
+package android.telephony.ims;
 
+import android.annotation.SystemApi;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -32,7 +33,8 @@
  * Parcelable object to handle MultiEndpoint Dialog Information
  * @hide
  */
-public class ImsExternalCallState implements Parcelable {
+@SystemApi
+public final class ImsExternalCallState implements Parcelable {
 
     private static final String TAG = "ImsExternalCallState";
 
@@ -50,9 +52,11 @@
     private int mCallType;
     private boolean mIsHeld;
 
+    /** @hide */
     public ImsExternalCallState() {
     }
 
+    /** @hide */
     public ImsExternalCallState(int callId, Uri address, boolean isPullable, int callState,
             int callType, boolean isCallheld) {
         mCallId = callId;
@@ -64,6 +68,7 @@
         Rlog.d(TAG, "ImsExternalCallState = " + this);
     }
 
+    /** @hide */
     public ImsExternalCallState(Parcel in) {
         mCallId = in.readInt();
         ClassLoader classLoader = ImsExternalCallState.class.getClassLoader();
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.aidl b/telephony/java/android/telephony/ims/ImsReasonInfo.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsReasonInfo.aidl
rename to telephony/java/android/telephony/ims/ImsReasonInfo.aidl
index 17e6d3a..604b323 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.aidl
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.ims;
+package android.telephony.ims;
 
 parcelable ImsReasonInfo;
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
similarity index 97%
rename from telephony/java/com/android/ims/ImsReasonInfo.java
rename to telephony/java/android/telephony/ims/ImsReasonInfo.java
index 83d9bd9..7b77491 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 The Android Open Source Project
+ * 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.
@@ -11,11 +11,12 @@
  * 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.
+ * limitations under the License
  */
 
-package com.android.ims;
+package android.telephony.ims;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -24,7 +25,8 @@
  *
  * @hide
  */
-public class ImsReasonInfo implements Parcelable {
+@SystemApi
+public final class ImsReasonInfo implements Parcelable {
 
     /**
      * Specific code of each types
@@ -418,27 +420,36 @@
 
 
     // For main reason code
+    /** @hide */
     public int mCode;
     // For the extra code value; it depends on the code value.
+    /** @hide */
     public int mExtraCode;
     // For the additional message of the reason info.
+    /** @hide */
     public String mExtraMessage;
+
+    /** @hide */
     public ImsReasonInfo() {
         mCode = CODE_UNSPECIFIED;
         mExtraCode = CODE_UNSPECIFIED;
         mExtraMessage = null;
     }
 
-    public ImsReasonInfo(Parcel in) {
-        readFromParcel(in);
+    private ImsReasonInfo(Parcel in) {
+        mCode = in.readInt();
+        mExtraCode = in.readInt();
+        mExtraMessage = in.readString();
     }
 
+    /** @hide */
     public ImsReasonInfo(int code, int extraCode) {
         mCode = code;
         mExtraCode = extraCode;
         mExtraMessage = null;
     }
 
+    /** @hide */
     public ImsReasonInfo(int code, int extraCode, String extraMessage) {
         mCode = code;
         mExtraCode = extraCode;
@@ -487,12 +498,6 @@
         out.writeString(mExtraMessage);
     }
 
-    private void readFromParcel(Parcel in) {
-        mCode = in.readInt();
-        mExtraCode = in.readInt();
-        mExtraMessage = in.readString();
-    }
-
     public static final Creator<ImsReasonInfo> CREATOR = new Creator<ImsReasonInfo>() {
         @Override
         public ImsReasonInfo createFromParcel(Parcel in) {
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index aaa0f08..2748cb5 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -16,25 +16,28 @@
 
 package android.telephony.ims;
 
-import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.telephony.CarrierConfigManager;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsMmTelFeature;
+import android.telephony.ims.aidl.IImsRcsFeature;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.aidl.IImsServiceController;
+import android.telephony.ims.aidl.IImsServiceControllerListener;
 import android.telephony.ims.feature.ImsFeature;
-import android.telephony.ims.feature.MMTelFeature;
+import android.telephony.ims.feature.MmTelFeature;
 import android.telephony.ims.feature.RcsFeature;
+import android.telephony.ims.stub.ImsConfigImplBase;
+import android.telephony.ims.stub.ImsFeatureConfiguration;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.util.Log;
 import android.util.SparseArray;
 
 import com.android.ims.internal.IImsFeatureStatusCallback;
-import com.android.ims.internal.IImsMMTelFeature;
-import com.android.ims.internal.IImsRcsFeature;
-import com.android.ims.internal.IImsRegistration;
-import com.android.ims.internal.IImsServiceController;
 import com.android.internal.annotations.VisibleForTesting;
 
 import static android.Manifest.permission.MODIFY_PHONE_STATE;
@@ -48,9 +51,7 @@
  * ...
  * <service android:name=".EgImsService"
  *     android:permission="android.permission.BIND_IMS_SERVICE" >
- *     <!-- Apps must declare which features they support as metadata. The different categories are
- *     defined below. In this example, the RCS_FEATURE feature is supported. -->
- *     <meta-data android:name="android.telephony.ims.RCS_FEATURE" android:value="true" />
+ *     ...
  *     <intent-filter>
  *         <action android:name="android.telephony.ims.ImsService" />
  *     </intent-filter>
@@ -64,13 +65,31 @@
  * 2) Defined as a Carrier Provided ImsService in the Carrier Configuration using
  *    {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}.
  *
+ * There are two ways to define to the platform which {@link ImsFeature}s this {@link ImsService}
+ * supports, dynamic or static definitions.
+ *
+ * In the static definition, the {@link ImsFeature}s that are supported are defined in the service
+ * definition of the AndroidManifest.xml file as metadata:
+ * <!-- Apps must declare which features they support as metadata. The different categories are
+ *      defined below. In this example, the MMTEL_FEATURE feature is supported. -->
+ * <meta-data android:name="android.telephony.ims.MMTEL_FEATURE" android:value="true" />
+ *
  * The features that are currently supported in an ImsService are:
  * - RCS_FEATURE: This ImsService implements the RcsFeature class.
- * - MMTEL_FEATURE: This ImsService implements the MMTelFeature class.
- * - EMERGENCY_MMTEL_FEATURE: This ImsService implements the MMTelFeature class and will be
- *   available to place emergency calls at all times. This MUST be implemented by the default
- *   ImsService provided in the device overlay.
- *   @hide
+ * - MMTEL_FEATURE: This ImsService implements the MmTelFeature class.
+ * - EMERGENCY_MMTEL_FEATURE: This ImsService supports Emergency Calling for MMTEL, must be
+ *   declared along with the MMTEL_FEATURE. If this is not specified, the framework will use
+ *   circuit switch for emergency calling.
+ *
+ * In the dynamic definition, the supported features are not specified in the service definition
+ * of the AndroidManifest. Instead, the framework binds to this service and calls
+ * {@link #querySupportedImsFeatures()}. The {@link ImsService} then returns an
+ * {@link ImsFeatureConfiguration}, which the framework uses to initialize the supported
+ * {@link ImsFeature}s. If at any time, the list of supported {@link ImsFeature}s changes,
+ * {@link #onUpdateSupportedImsFeatures(ImsFeatureConfiguration)} can be called to tell the
+ * framework of the changes.
+ *
+ * @hide
  */
 @SystemApi
 public class ImsService extends Service {
@@ -89,20 +108,36 @@
     // call ImsFeature#onFeatureRemoved.
     private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>();
 
+    private IImsServiceControllerListener mListener;
+
+
+    /**
+     * Listener that notifies the framework of ImsService changes.
+     * @hide
+     */
+    public static class Listener extends IImsServiceControllerListener.Stub {
+        /**
+         * The IMS features that this ImsService supports has changed.
+         * @param c a new {@link ImsFeatureConfiguration} containing {@link ImsFeature.FeatureType}s
+         *   that this ImsService supports. This may trigger the addition/removal of feature
+         *   in this service.
+         */
+        public void onUpdateSupportedImsFeatures(ImsFeatureConfiguration c) {
+        }
+    }
+
     /**
      * @hide
      */
     protected final IBinder mImsServiceController = new IImsServiceController.Stub() {
-
         @Override
-        public IImsMMTelFeature createEmergencyMMTelFeature(int slotId,
-                IImsFeatureStatusCallback c) {
-            return createEmergencyMMTelFeatureInternal(slotId, c);
+        public void setListener(IImsServiceControllerListener l) {
+            mListener = l;
         }
 
         @Override
-        public IImsMMTelFeature createMMTelFeature(int slotId, IImsFeatureStatusCallback c) {
-            return createMMTelFeatureInternal(slotId, c);
+        public IImsMmTelFeature createMmTelFeature(int slotId, IImsFeatureStatusCallback c) {
+            return createMmTelFeatureInternal(slotId, c);
         }
 
         @Override
@@ -111,16 +146,46 @@
         }
 
         @Override
-        public void removeImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c)
-                throws RemoteException {
+        public void removeImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c) {
             ImsService.this.removeImsFeature(slotId, featureType, c);
         }
 
         @Override
-        public IImsRegistration getRegistration(int slotId) throws RemoteException {
+        public ImsFeatureConfiguration querySupportedImsFeatures() {
+            return ImsService.this.querySupportedImsFeatures();
+        }
+
+        @Override
+        public void notifyImsServiceReadyForFeatureCreation() {
+            ImsService.this.readyForFeatureCreation();
+        }
+
+        @Override
+        public void notifyImsFeatureReady(int slotId, int featureType) {
+            ImsService.this.notifyImsFeatureReady(slotId, featureType);
+        }
+
+        @Override
+        public IImsConfig getConfig(int slotId) {
+            ImsConfigImplBase c = ImsService.this.getConfig(slotId);
+            return c != null ? c.getIImsConfig() : null;
+        }
+
+        @Override
+        public IImsRegistration getRegistration(int slotId) {
             ImsRegistrationImplBase r = ImsService.this.getRegistration(slotId);
             return r != null ? r.getBinder() : null;
         }
+
+        @Override
+        public void enableIms(int slotId) {
+            ImsService.this.enableIms(slotId);
+        }
+
+        @Override
+        public void disableIms(int slotId) {
+            ImsService.this.disableIms(slotId);
+        }
     };
 
     /**
@@ -143,47 +208,35 @@
         return mFeaturesBySlot.get(slotId);
     }
 
-    private IImsMMTelFeature createEmergencyMMTelFeatureInternal(int slotId,
+    private IImsMmTelFeature createMmTelFeatureInternal(int slotId,
             IImsFeatureStatusCallback c) {
-        MMTelFeature f = onCreateEmergencyMMTelImsFeature(slotId);
+        MmTelFeature f = createMmTelFeature(slotId);
         if (f != null) {
-            setupFeature(f, slotId, ImsFeature.EMERGENCY_MMTEL, c);
+            setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL, c);
             return f.getBinder();
         } else {
-            return null;
-        }
-    }
-
-    private IImsMMTelFeature createMMTelFeatureInternal(int slotId,
-            IImsFeatureStatusCallback c) {
-        MMTelFeature f = onCreateMMTelImsFeature(slotId);
-        if (f != null) {
-            setupFeature(f, slotId, ImsFeature.MMTEL, c);
-            return f.getBinder();
-        } else {
+            Log.e(LOG_TAG, "createMmTelFeatureInternal: null feature returned.");
             return null;
         }
     }
 
     private IImsRcsFeature createRcsFeatureInternal(int slotId,
             IImsFeatureStatusCallback c) {
-        RcsFeature f = onCreateRcsFeature(slotId);
+        RcsFeature f = createRcsFeature(slotId);
         if (f != null) {
-            setupFeature(f, slotId, ImsFeature.RCS, c);
+            setupFeature(f, slotId, ImsFeature.FEATURE_RCS, c);
             return f.getBinder();
         } else {
+            Log.e(LOG_TAG, "createRcsFeatureInternal: null feature returned.");
             return null;
         }
     }
 
     private void setupFeature(ImsFeature f, int slotId, int featureType,
             IImsFeatureStatusCallback c) {
-        f.setContext(this);
-        f.setSlotId(slotId);
         f.addImsFeatureStatusCallback(c);
+        f.initialize(this, slotId);
         addImsFeature(slotId, featureType, f);
-        // TODO: Remove once new onFeatureReady AIDL is merged in.
-        f.onFeatureReady();
     }
 
     private void addImsFeature(int slotId, int featureType, ImsFeature f) {
@@ -221,38 +274,122 @@
         }
     }
 
+    private void notifyImsFeatureReady(int slotId, int featureType) {
+        synchronized (mFeaturesBySlot) {
+            // get ImsFeature associated with the slot/feature
+            SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
+            if (features == null) {
+                Log.w(LOG_TAG, "Can not notify ImsFeature ready. No ImsFeatures exist on " +
+                        "slot " + slotId);
+                return;
+            }
+            ImsFeature f = features.get(featureType);
+            if (f == null) {
+                Log.w(LOG_TAG, "Can not notify ImsFeature ready. No feature with type "
+                        + featureType + " exists on slot " + slotId);
+                return;
+            }
+            f.onFeatureReady();
+        }
+    }
+
     /**
-     * @return An implementation of MMTelFeature that will be used by the system for MMTel
-     * functionality. Must be able to handle emergency calls at any time as well.
-     * @hide
+     * When called, provide the {@link ImsFeatureConfiguration} that this {@link ImsService}
+     * currently supports. This will trigger the framework to set up the {@link ImsFeature}s that
+     * correspond to the {@link ImsFeature}s configured here.
+     *
+     * Use {@link #onUpdateSupportedImsFeatures(ImsFeatureConfiguration)} to change the supported
+     * {@link ImsFeature}s.
+     *
+     * @return an {@link ImsFeatureConfiguration} containing Features this ImsService supports.
      */
-    public @Nullable MMTelFeature onCreateEmergencyMMTelImsFeature(int slotId) {
+    public ImsFeatureConfiguration querySupportedImsFeatures() {
+        // Return empty for base implementation
+        return new ImsFeatureConfiguration();
+    }
+
+    /**
+     * Updates the framework with a new {@link ImsFeatureConfiguration} containing the updated
+     * features, that this {@link ImsService} supports. This may trigger the framework to add/remove
+     * new ImsFeatures, depending on the configuration.
+     */
+    public final void onUpdateSupportedImsFeatures(ImsFeatureConfiguration c)
+            throws RemoteException {
+        if (mListener == null) {
+            throw new IllegalStateException("Framework is not ready");
+        }
+        mListener.onUpdateSupportedImsFeatures(c);
+    }
+
+    /**
+     * The ImsService has been bound and is ready for ImsFeature creation based on the Features that
+     * the ImsService has registered for with the framework, either in the manifest or via
+     * {@link #querySupportedImsFeatures()}.
+     *
+     * The ImsService should use this signal instead of onCreate/onBind or similar to perform
+     * feature initialization because the framework may bind to this service multiple times to
+     * query the ImsService's {@link ImsFeatureConfiguration} via
+     * {@link #querySupportedImsFeatures()}before creating features.
+     */
+    public void readyForFeatureCreation() {
+    }
+
+    /**
+     * The framework has enabled IMS for the slot specified, the ImsService should register for IMS
+     * and perform all appropriate initialization to bring up all ImsFeatures.
+     */
+    public void enableIms(int slotId) {
+    }
+
+    /**
+     * The framework has disabled IMS for the slot specified. The ImsService must deregister for IMS
+     * and set capability status to false for all ImsFeatures.
+     */
+    public void disableIms(int slotId) {
+    }
+
+    /**
+     * When called, the framework is requesting that a new {@link MmTelFeature} is created for the
+     * specified slot.
+     *
+     * @param slotId The slot ID that the MMTEL Feature is being created for.
+     * @return The newly created {@link MmTelFeature} associated with the slot or null if the
+     * feature is not supported.
+     */
+    public MmTelFeature createMmTelFeature(int slotId) {
         return null;
     }
 
     /**
-     * @return An implementation of MMTelFeature that will be used by the system for MMTel
-     * functionality.
-     * @hide
+     * When called, the framework is requesting that a new {@link RcsFeature} is created for the
+     * specified slot.
+     *
+     * @param slotId The slot ID that the RCS Feature is being created for.
+     * @return The newly created {@link RcsFeature} associated with the slot or null if the feature
+     * is not supported.
      */
-    public @Nullable MMTelFeature onCreateMMTelImsFeature(int slotId) {
+    public RcsFeature createRcsFeature(int slotId) {
         return null;
     }
 
     /**
-     * @return An implementation of RcsFeature that will be used by the system for RCS.
-     * @hide
+     * Return the {@link ImsConfigImplBase} implementation associated with the provided slot. This
+     * will be used by the platform to get/set specific IMS related configurations.
+     *
+     * @param slotId The slot that the IMS configuration is associated with.
+     * @return ImsConfig implementation that is associated with the specified slot.
      */
-    public @Nullable RcsFeature onCreateRcsFeature(int slotId) {
-        return null;
+    public ImsConfigImplBase getConfig(int slotId) {
+        return new ImsConfigImplBase();
     }
 
     /**
+     * Return the {@link ImsRegistrationImplBase} implementation associated with the provided slot.
+     *
      * @param slotId The slot that is associated with the IMS Registration.
      * @return the ImsRegistration implementation associated with the slot.
-     * @hide
      */
     public ImsRegistrationImplBase getRegistration(int slotId) {
         return new ImsRegistrationImplBase();
     }
-}
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/ims/ImsSsData.aidl b/telephony/java/android/telephony/ims/ImsSsData.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsSsData.aidl
rename to telephony/java/android/telephony/ims/ImsSsData.aidl
index 33f8306..eff3a6b 100644
--- a/telephony/java/com/android/ims/ImsSsData.aidl
+++ b/telephony/java/android/telephony/ims/ImsSsData.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.ims;
+package android.telephony.ims;
 
 parcelable ImsSsData;
diff --git a/telephony/java/com/android/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java
similarity index 89%
rename from telephony/java/com/android/ims/ImsSsData.java
rename to telephony/java/android/telephony/ims/ImsSsData.java
index 7336c13..1ddf199 100644
--- a/telephony/java/com/android/ims/ImsSsData.java
+++ b/telephony/java/android/telephony/ims/ImsSsData.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 The Android Open Source Project
+ * 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.
@@ -11,21 +11,21 @@
  * 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.
+ * limitations under the License
  */
-package com.android.ims;
+package android.telephony.ims;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.util.ArrayList;
-
 /**
  * Provided STK Call Control Suplementary Service information
  *
  * {@hide}
  */
-public class ImsSsData implements Parcelable {
+@SystemApi
+public final class ImsSsData implements Parcelable {
 
     //ServiceType
     public static final int SS_CFU = 0;
@@ -68,30 +68,38 @@
     public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5;
 
     // Refer to ServiceType
+    /** @hide */
     public int serviceType;
     // Refere to SSRequestType
+    /** @hide */
     public int requestType;
     // Refer to TeleserviceType
+    /** @hide */
     public int teleserviceType;
     // Service Class
+    /** @hide */
     public int serviceClass;
     // Error information
+    /** @hide */
     public int result;
 
+    /** @hide */
     public int[] ssInfo; /* Valid for all supplementary services.
                              This field will be empty for RequestType SS_INTERROGATION
                              and ServiceType SS_CF_*, SS_INCOMING_BARRING_DN,
                              SS_INCOMING_BARRING_ANONYMOUS.*/
 
+    /** @hide */
     public ImsCallForwardInfo[] cfInfo; /* Valid only for supplementary services
                                             ServiceType SS_CF_* and RequestType SS_INTERROGATION */
 
+    /** @hide */
     public ImsSsInfo[] imsSsInfo;   /* Valid only for ServiceType SS_INCOMING_BARRING_DN and
                                         ServiceType SS_INCOMING_BARRING_ANONYMOUS */
 
     public ImsSsData() {}
 
-    public ImsSsData(Parcel in) {
+    private ImsSsData(Parcel in) {
         readFromParcel(in);
     }
 
@@ -133,20 +141,36 @@
         return 0;
     }
 
+    /**
+     * Old method, kept for compatibility. See {@link #isTypeCf()}
+     * @hide
+     */
     public boolean isTypeCF() {
         return (serviceType == SS_CFU || serviceType == SS_CF_BUSY ||
               serviceType == SS_CF_NO_REPLY || serviceType == SS_CF_NOT_REACHABLE ||
               serviceType == SS_CF_ALL || serviceType == SS_CF_ALL_CONDITIONAL);
     }
 
+    public boolean isTypeCf() {
+        return isTypeCF();
+    }
+
     public boolean isTypeUnConditional() {
         return (serviceType == SS_CFU || serviceType == SS_CF_ALL);
     }
 
+    /**
+     * Old method, kept for compatibility. See {@link #isTypeCf()}
+     * @hide
+     */
     public boolean isTypeCW() {
         return (serviceType == SS_WAIT);
     }
 
+    public boolean isTypeCw() {
+        return isTypeCW();
+    }
+
     public boolean isTypeClip() {
         return (serviceType == SS_CLIP);
     }
diff --git a/telephony/java/com/android/ims/ImsSsInfo.aidl b/telephony/java/android/telephony/ims/ImsSsInfo.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsSsInfo.aidl
rename to telephony/java/android/telephony/ims/ImsSsInfo.aidl
index 0ac598b..66d4950 100644
--- a/telephony/java/com/android/ims/ImsSsInfo.aidl
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.ims;
+package android.telephony.ims;
 
 parcelable ImsSsInfo;
diff --git a/telephony/java/com/android/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java
similarity index 81%
rename from telephony/java/com/android/ims/ImsSsInfo.java
rename to telephony/java/android/telephony/ims/ImsSsInfo.java
index 7acc3bf..1d1292f 100644
--- a/telephony/java/com/android/ims/ImsSsInfo.java
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 The Android Open Source Project
+ * 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.
@@ -11,11 +11,12 @@
  * 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.
+ * limitations under the License
  */
 
-package com.android.ims;
+package android.telephony.ims;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -24,7 +25,8 @@
  *
  * @hide
  */
-public class ImsSsInfo implements Parcelable {
+@SystemApi
+public final class ImsSsInfo implements Parcelable {
     /**
      * For the status of service registration or activation/deactivation.
      */
@@ -33,13 +35,15 @@
     public static final int ENABLED = 1;
 
     // 0: disabled, 1: enabled
+    /** @hide */
     public int mStatus;
+    /** @hide */
     public String mIcbNum;
 
     public ImsSsInfo() {
     }
 
-    public ImsSsInfo(Parcel in) {
+    private ImsSsInfo(Parcel in) {
         readFromParcel(in);
     }
 
@@ -76,4 +80,12 @@
             return new ImsSsInfo[size];
         }
     };
+
+    public int getStatus() {
+        return mStatus;
+    }
+
+    public String getIcbNum() {
+        return mIcbNum;
+    }
 }
diff --git a/telephony/java/com/android/ims/ImsStreamMediaProfile.aidl b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsStreamMediaProfile.aidl
rename to telephony/java/android/telephony/ims/ImsStreamMediaProfile.aidl
index d648a35..ee321ae 100644
--- a/telephony/java/com/android/ims/ImsStreamMediaProfile.aidl
+++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.ims;
+package android.telephony.ims;
 
 parcelable ImsStreamMediaProfile;
diff --git a/telephony/java/com/android/ims/ImsStreamMediaProfile.java b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
similarity index 88%
rename from telephony/java/com/android/ims/ImsStreamMediaProfile.java
rename to telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
index cfe37b5..243352b 100644
--- a/telephony/java/com/android/ims/ImsStreamMediaProfile.java
+++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 The Android Open Source Project
+ * 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.
@@ -11,11 +11,12 @@
  * 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.
+ * limitations under the License
  */
 
-package com.android.ims;
+package android.telephony.ims;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -25,7 +26,8 @@
  *
  * @hide
  */
-public class ImsStreamMediaProfile implements Parcelable {
+@SystemApi
+public final class ImsStreamMediaProfile implements Parcelable {
     private static final String TAG = "ImsStreamMediaProfile";
 
     /**
@@ -79,18 +81,25 @@
     public static final int RTT_MODE_FULL = 1;
 
     // Audio related information
+    /** @hide */
     public int mAudioQuality;
+    /** @hide */
     public int mAudioDirection;
     // Video related information
+    /** @hide */
     public int mVideoQuality;
+    /** @hide */
     public int mVideoDirection;
     // Rtt related information
+    /** @hide */
     public int mRttMode;
 
+    /** @hide */
     public ImsStreamMediaProfile(Parcel in) {
         readFromParcel(in);
     }
 
+    /** @hide */
     public ImsStreamMediaProfile() {
         mAudioQuality = AUDIO_QUALITY_NONE;
         mAudioDirection = DIRECTION_SEND_RECEIVE;
@@ -99,6 +108,7 @@
         mRttMode = RTT_MODE_DISABLED;
     }
 
+    /** @hide */
     public ImsStreamMediaProfile(int audioQuality, int audioDirection,
             int videoQuality, int videoDirection) {
         mAudioQuality = audioQuality;
@@ -107,6 +117,7 @@
         mVideoDirection = videoDirection;
     }
 
+    /** @hide */
     public ImsStreamMediaProfile(int rttMode) {
         mRttMode = rttMode;
     }
@@ -178,4 +189,23 @@
         mRttMode = rttMode;
     }
 
+    public int getAudioQuality() {
+        return mAudioQuality;
+    }
+
+    public int getAudioDirection() {
+        return mAudioDirection;
+    }
+
+    public int getVideoQuality() {
+        return mVideoQuality;
+    }
+
+    public int getVideoDirection() {
+        return mVideoDirection;
+    }
+
+    public int getRttMode() {
+        return mRttMode;
+    }
 }
diff --git a/telephony/java/com/android/ims/ImsSuppServiceNotification.aidl b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsSuppServiceNotification.aidl
rename to telephony/java/android/telephony/ims/ImsSuppServiceNotification.aidl
index 6b4479f..0552780 100644
--- a/telephony/java/com/android/ims/ImsSuppServiceNotification.aidl
+++ b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.aidl
@@ -15,6 +15,6 @@
  */
 
 
-package com.android.ims;
+package android.telephony.ims;
 
 parcelable ImsSuppServiceNotification;
diff --git a/telephony/java/com/android/ims/ImsSuppServiceNotification.java b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
similarity index 76%
rename from telephony/java/com/android/ims/ImsSuppServiceNotification.java
rename to telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
index faf7499..efaade8 100644
--- a/telephony/java/com/android/ims/ImsSuppServiceNotification.java
+++ b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 The Android Open Source Project
+ * 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.
@@ -11,12 +11,13 @@
  * 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.
+ * limitations under the License
  */
 
 
-package com.android.ims;
+package android.telephony.ims;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -28,27 +29,42 @@
  *
  * @hide
  */
-public class ImsSuppServiceNotification implements Parcelable {
+@SystemApi
+public final class ImsSuppServiceNotification implements Parcelable {
     private static final String TAG = "ImsSuppServiceNotification";
 
     /** Type of notification: 0 = MO; 1 = MT */
-    public int notificationType;
+    public final int notificationType;
     /** TS 27.007 7.17 "code1" or "code2" */
-    public int code;
+    public final int code;
     /** TS 27.007 7.17 "index" - Not used currently*/
-    public int index;
+    public final int index;
     /** TS 27.007 7.17 "type" (MT only) - Not used currently */
-    public int type;
+    public final int type;
     /** TS 27.007 7.17 "number" (MT only) */
-    public String number;
+    public final String number;
     /** List of forwarded numbers, if any */
-    public String[] history;
+    public final String[] history;
 
-    public ImsSuppServiceNotification() {
+
+    public ImsSuppServiceNotification(int notificationType, int code, int index, int type,
+            String number, String[] history) {
+        this.notificationType = notificationType;
+        this.code = code;
+        this.index = index;
+        this.type = type;
+        this.number = number;
+        this.history = history;
     }
 
+    /** @hide */
     public ImsSuppServiceNotification(Parcel in) {
-        readFromParcel(in);
+        notificationType = in.readInt();
+        code = in.readInt();
+        index = in.readInt();
+        type = in.readInt();
+        number = in.readString();
+        history = in.createStringArray();
     }
 
     @Override
@@ -77,15 +93,6 @@
         out.writeStringArray(history);
     }
 
-    private void readFromParcel(Parcel in) {
-        notificationType = in.readInt();
-        code = in.readInt();
-        index = in.readInt();
-        type = in.readInt();
-        number = in.readString();
-        history = in.createStringArray();
-    }
-
     public static final Creator<ImsSuppServiceNotification> CREATOR =
             new Creator<ImsSuppServiceNotification>() {
         @Override
diff --git a/telephony/java/android/telephony/ims/ImsUtListener.java b/telephony/java/android/telephony/ims/ImsUtListener.java
new file mode 100644
index 0000000..d50a0f7
--- /dev/null
+++ b/telephony/java/android/telephony/ims/ImsUtListener.java
@@ -0,0 +1,108 @@
+/*
+ * 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.SystemApi;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.ims.internal.IImsUtListener;
+
+/**
+ * Base implementation of the IMS UT listener interface, which implements stubs.
+ * Override these methods to implement functionality.
+ * @hide
+ */
+// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+// will break other implementations of ImsUt maintained by other ImsServices.
+@SystemApi
+public class ImsUtListener {
+    private IImsUtListener mServiceInterface;
+    private static final String LOG_TAG = "ImsUtListener";
+
+    public void onUtConfigurationUpdated(int id) {
+        try {
+            mServiceInterface.utConfigurationUpdated(null, id);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "utConfigurationUpdated: remote exception");
+        }
+    }
+
+    public void onUtConfigurationUpdateFailed(int id, ImsReasonInfo error) {
+        try {
+            mServiceInterface.utConfigurationUpdateFailed(null, id, error);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "utConfigurationUpdateFailed: remote exception");
+        }
+    }
+
+    public void onUtConfigurationQueried(int id, Bundle ssInfo) {
+        try {
+            mServiceInterface.utConfigurationQueried(null, id, ssInfo);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "utConfigurationQueried: remote exception");
+        }
+    }
+
+    public void onUtConfigurationQueryFailed(int id, ImsReasonInfo error) {
+        try {
+            mServiceInterface.utConfigurationQueryFailed(null, id, error);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "utConfigurationQueryFailed: remote exception");
+        }
+    }
+
+    public void onUtConfigurationCallBarringQueried(int id, ImsSsInfo[] cbInfo) {
+        try {
+            mServiceInterface.utConfigurationCallBarringQueried(null, id, cbInfo);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "utConfigurationCallBarringQueried: remote exception");
+        }
+    }
+
+    public void onUtConfigurationCallForwardQueried(int id, ImsCallForwardInfo[] cfInfo) {
+        try {
+            mServiceInterface.utConfigurationCallForwardQueried(null, id, cfInfo);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "utConfigurationCallForwardQueried: remote exception");
+        }
+    }
+
+    public void onUtConfigurationCallWaitingQueried(int id, ImsSsInfo[] cwInfo) {
+        try {
+            mServiceInterface.utConfigurationCallWaitingQueried(null, id, cwInfo);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "utConfigurationCallWaitingQueried: remote exception");
+        }
+    }
+
+    public void onSupplementaryServiceIndication(ImsSsData ssData) {
+        try {
+            mServiceInterface.onSupplementaryServiceIndication(ssData);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "onSupplementaryServiceIndication: remote exception");
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public ImsUtListener(IImsUtListener serviceInterface) {
+        mServiceInterface = serviceInterface;
+    }
+}
diff --git a/telephony/java/com/android/ims/internal/ImsVideoCallProvider.java b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
similarity index 97%
rename from telephony/java/com/android/ims/internal/ImsVideoCallProvider.java
rename to telephony/java/android/telephony/ims/ImsVideoCallProvider.java
index 432dc39..b4f60b9 100644
--- a/telephony/java/com/android/ims/internal/ImsVideoCallProvider.java
+++ b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,8 +14,9 @@
  * limitations under the License
  */
 
-package com.android.ims.internal;
+package android.telephony.ims;
 
+import android.annotation.SystemApi;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
@@ -26,11 +27,14 @@
 import android.telecom.VideoProfile.CameraCapabilities;
 import android.view.Surface;
 
+import com.android.ims.internal.IImsVideoCallCallback;
+import com.android.ims.internal.IImsVideoCallProvider;
 import com.android.internal.os.SomeArgs;
 
 /**
  * @hide
  */
+@SystemApi
 public abstract class ImsVideoCallProvider {
     private static final int MSG_SET_CALLBACK = 1;
     private static final int MSG_SET_CAMERA = 2;
@@ -173,6 +177,7 @@
 
     /**
      * Returns binder object which can be used across IPC methods.
+     * @hide
      */
     public final IImsVideoCallProvider getInterface() {
         return mBinder;
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsCallSessionListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl
similarity index 94%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsCallSessionListener.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl
index 2fb6744..f25b4b1 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsCallSessionListener.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
 
-import com.android.ims.ImsStreamMediaProfile;
-import com.android.ims.ImsCallProfile;
-import com.android.ims.ImsReasonInfo;
-import com.android.ims.ImsConferenceState;
+import android.telephony.ims.ImsStreamMediaProfile;
+import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsConferenceState;
 import com.android.ims.internal.IImsCallSession;
-import com.android.ims.ImsSuppServiceNotification;
+import android.telephony.ims.ImsSuppServiceNotification;
 
 /**
  * A listener type for receiving notification on IMS call session events.
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsCapabilityCallback.aidl b/telephony/java/android/telephony/ims/aidl/IImsCapabilityCallback.aidl
similarity index 95%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsCapabilityCallback.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsCapabilityCallback.aidl
index fd2eb24..c755703 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsCapabilityCallback.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsCapabilityCallback.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
 
 /**
  * See ImsFeature#CapabilityCallback for more information.
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsConfig.aidl b/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl
similarity index 91%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsConfig.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsConfig.aidl
index 3d424a3..4433c1c 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsConfig.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl
@@ -15,9 +15,9 @@
  */
 
 
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
 
-import android.telephony.ims.internal.aidl.IImsConfigCallback;
+import android.telephony.ims.aidl.IImsConfigCallback;
 
 import com.android.ims.ImsConfigListener;
 
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsConfigCallback.aidl b/telephony/java/android/telephony/ims/aidl/IImsConfigCallback.aidl
similarity index 94%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsConfigCallback.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsConfigCallback.aidl
index 52efd23..2b3f1ca 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsConfigCallback.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsConfigCallback.aidl
@@ -15,7 +15,7 @@
  */
 
 
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
 
 /**
  * Provides callback interface for ImsConfig when a value has changed.
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl b/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl
similarity index 66%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl
index e226ada..b9a6b3c 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
 
 import android.os.Message;
-import android.telephony.ims.internal.aidl.IImsMmTelListener;
-import android.telephony.ims.internal.aidl.IImsCapabilityCallback;
-import android.telephony.ims.internal.aidl.IImsCallSessionListener;
-import android.telephony.ims.internal.feature.CapabilityChangeRequest;
+import android.telephony.ims.aidl.IImsMmTelListener;
+import android.telephony.ims.aidl.IImsSmsListener;
+import android.telephony.ims.aidl.IImsCapabilityCallback;
+import android.telephony.ims.feature.CapabilityChangeRequest;
 
-import com.android.ims.ImsCallProfile;
+import android.telephony.ims.ImsCallProfile;
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsEcbm;
 import com.android.ims.internal.IImsMultiEndpoint;
@@ -30,14 +30,15 @@
 import com.android.ims.internal.IImsUt;
 
 /**
- * See SmsImplBase for more information.
+ * See MmTelFeature for more information.
  * {@hide}
  */
 interface IImsMmTelFeature {
     void setListener(IImsMmTelListener l);
     int getFeatureState();
     ImsCallProfile createCallProfile(int callSessionType, int callType);
-    IImsCallSession createCallSession(in ImsCallProfile profile, IImsCallSessionListener listener);
+    IImsCallSession createCallSession(in ImsCallProfile profile);
+    int shouldProcessCall(in String[] uris);
     IImsUt getUtInterface();
     IImsEcbm getEcbmInterface();
     void setUiTtyMode(int uiTtyMode, in Message onCompleteMessage);
@@ -49,4 +50,12 @@
             IImsCapabilityCallback c);
     oneway void queryCapabilityConfiguration(int capability, int radioTech,
             IImsCapabilityCallback c);
+    // SMS APIs
+    void setSmsListener(IImsSmsListener l);
+    oneway void sendSms(in int token, int messageRef, String format, String smsc, boolean retry,
+            in byte[] pdu);
+    oneway void acknowledgeSms(int token, int messageRef, int result);
+    oneway void acknowledgeSmsReport(int token, int messageRef, int result);
+    String getSmsFormat();
+    oneway void onSmsReady();
 }
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl
similarity index 86%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl
index 43f5098..904e7ca 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
+
+import android.os.Bundle;
 
 import com.android.ims.internal.IImsCallSession;
 
@@ -23,6 +25,6 @@
  * {@hide}
  */
 oneway interface IImsMmTelListener {
-    void onIncomingCall(IImsCallSession c);
+    void onIncomingCall(IImsCallSession c, in Bundle extras);
     void onVoiceMessageCountUpdate(int count);
 }
\ No newline at end of file
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl
similarity index 94%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl
index f6005b6..691cfba 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
 
 /**
  * See RcsFeature for more information.
diff --git a/telephony/java/com/android/ims/internal/IImsRegistration.aidl b/telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl
similarity index 90%
rename from telephony/java/com/android/ims/internal/IImsRegistration.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl
index 6de264e..4ae0a75 100644
--- a/telephony/java/com/android/ims/internal/IImsRegistration.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl
@@ -15,9 +15,9 @@
  */
 
 
-package com.android.ims.internal;
+package android.telephony.ims.aidl;
 
-import com.android.ims.internal.IImsRegistrationCallback;
+import android.telephony.ims.aidl.IImsRegistrationCallback;
 
 /**
  * See ImsRegistration for more information.
diff --git a/telephony/java/com/android/ims/internal/IImsRegistrationCallback.aidl b/telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl
similarity index 87%
rename from telephony/java/com/android/ims/internal/IImsRegistrationCallback.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl
index 5f21167..4f37caa 100644
--- a/telephony/java/com/android/ims/internal/IImsRegistrationCallback.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl
@@ -15,12 +15,12 @@
  */
 
 
-package com.android.ims.internal;
+package android.telephony.ims.aidl;
 
 import android.net.Uri;
-import android.telephony.ims.internal.stub.ImsFeatureConfiguration;
+import android.telephony.ims.stub.ImsFeatureConfiguration;
 
-import com.android.ims.ImsReasonInfo;
+import android.telephony.ims.ImsReasonInfo;
 
 /**
  * See ImsRegistrationImplBase.Callback for more information.
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
similarity index 77%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
index 82a8525..86f8606 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
 
-import android.telephony.ims.internal.aidl.IImsMmTelFeature;
-import android.telephony.ims.internal.aidl.IImsRcsFeature;
-import android.telephony.ims.internal.aidl.IImsConfig;
-import android.telephony.ims.internal.aidl.IImsServiceControllerListener;
-import android.telephony.ims.internal.stub.ImsFeatureConfiguration;
+import android.telephony.ims.aidl.IImsMmTelFeature;
+import android.telephony.ims.aidl.IImsRcsFeature;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.aidl.IImsServiceControllerListener;
+import android.telephony.ims.stub.ImsFeatureConfiguration;
 
 import com.android.ims.internal.IImsFeatureStatusCallback;
-import com.android.ims.internal.IImsRegistration;
 
 /**
  * See ImsService and MmTelFeature for more information.
@@ -41,4 +41,6 @@
     void removeImsFeature(int slotId, int featureType, in IImsFeatureStatusCallback c);
     IImsConfig getConfig(int slotId);
     IImsRegistration getRegistration(int slotId);
+    oneway void enableIms(int slotId);
+    oneway void disableIms(int slotId);
 }
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceControllerListener.aidl
similarity index 87%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsServiceControllerListener.aidl
index 01cca2db..54f6120 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsServiceControllerListener.aidl
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
 
-import android.telephony.ims.internal.stub.ImsFeatureConfiguration;
+import android.telephony.ims.stub.ImsFeatureConfiguration;
 
 /**
  * See ImsService#Listener for more information.
diff --git a/telephony/java/com/android/ims/internal/IImsSmsListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl
similarity index 92%
rename from telephony/java/com/android/ims/internal/IImsSmsListener.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl
index 5a4b7e4..606df15 100644
--- a/telephony/java/com/android/ims/internal/IImsSmsListener.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.ims.internal;
+package android.telephony.ims.aidl;
 
 /**
  * See SmsImplBase for more information.
  * {@hide}
  */
-interface IImsSmsListener {
+oneway interface IImsSmsListener {
     void onSendSmsResult(int token, int messageRef, int status, int reason);
     void onSmsStatusReportReceived(int token, int messageRef, in String format,
             in byte[] pdu);
diff --git a/telephony/java/android/telephony/ims/compat/ImsService.java b/telephony/java/android/telephony/ims/compat/ImsService.java
new file mode 100644
index 0000000..cf1efb3
--- /dev/null
+++ b/telephony/java/android/telephony/ims/compat/ImsService.java
@@ -0,0 +1,237 @@
+/*
+ * 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.compat;
+
+import android.annotation.Nullable;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.telephony.CarrierConfigManager;
+import android.telephony.ims.compat.feature.ImsFeature;
+import android.telephony.ims.compat.feature.MMTelFeature;
+import android.telephony.ims.compat.feature.RcsFeature;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.ims.internal.IImsFeatureStatusCallback;
+import com.android.ims.internal.IImsMMTelFeature;
+import com.android.ims.internal.IImsRcsFeature;
+import com.android.ims.internal.IImsServiceController;
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend
+ * ImsService must register the service in their AndroidManifest to be detected by the framework.
+ * First, the application must declare that they use the "android.permission.BIND_IMS_SERVICE"
+ * permission. Then, the ImsService definition in the manifest must follow the following format:
+ *
+ * ...
+ * <service android:name=".EgImsService"
+ *     android:permission="android.permission.BIND_IMS_SERVICE" >
+ *     <!-- Apps must declare which features they support as metadata. The different categories are
+ *     defined below. In this example, the RCS_FEATURE feature is supported. -->
+ *     <meta-data android:name="android.telephony.ims.RCS_FEATURE" android:value="true" />
+ *     <intent-filter>
+ *         <action android:name="android.telephony.ims.compat.ImsService" />
+ *     </intent-filter>
+ * </service>
+ * ...
+ *
+ * The telephony framework will then bind to the ImsService you have defined in your manifest
+ * if you are either:
+ * 1) Defined as the default ImsService for the device in the device overlay using
+ *    "config_ims_package".
+ * 2) Defined as a Carrier Provided ImsService in the Carrier Configuration using
+ *    {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}.
+ *
+ * The features that are currently supported in an ImsService are:
+ * - RCS_FEATURE: This ImsService implements the RcsFeature class.
+ * - MMTEL_FEATURE: This ImsService implements the MMTelFeature class.
+ * - EMERGENCY_MMTEL_FEATURE: This ImsService implements the MMTelFeature class and will be
+ *   available to place emergency calls at all times. This MUST be implemented by the default
+ *   ImsService provided in the device overlay.
+ *   @hide
+ */
+public class ImsService extends Service {
+
+    private static final String LOG_TAG = "ImsService(Compat)";
+
+    /**
+     * The intent that must be defined as an intent-filter in the AndroidManifest of the ImsService.
+     * @hide
+     */
+    public static final String SERVICE_INTERFACE = "android.telephony.ims.compat.ImsService";
+
+    // A map of slot Id -> map of features (indexed by ImsFeature feature id) corresponding to that
+    // slot.
+    // We keep track of this to facilitate cleanup of the IImsFeatureStatusCallback and
+    // call ImsFeature#onFeatureRemoved.
+    private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>();
+
+    /**
+     * @hide
+     */
+    protected final IBinder mImsServiceController = new IImsServiceController.Stub() {
+
+        @Override
+        public IImsMMTelFeature createEmergencyMMTelFeature(int slotId,
+                IImsFeatureStatusCallback c) {
+            return createEmergencyMMTelFeatureInternal(slotId, c);
+        }
+
+        @Override
+        public IImsMMTelFeature createMMTelFeature(int slotId, IImsFeatureStatusCallback c) {
+            return createMMTelFeatureInternal(slotId, c);
+        }
+
+        @Override
+        public IImsRcsFeature createRcsFeature(int slotId, IImsFeatureStatusCallback c) {
+            return createRcsFeatureInternal(slotId, c);
+        }
+
+        @Override
+        public void removeImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c)
+                throws RemoteException {
+            ImsService.this.removeImsFeature(slotId, featureType, c);
+        }
+    };
+
+    /**
+     * @hide
+     */
+    @Override
+    public IBinder onBind(Intent intent) {
+        if(SERVICE_INTERFACE.equals(intent.getAction())) {
+            Log.i(LOG_TAG, "ImsService(Compat) Bound.");
+            return mImsServiceController;
+        }
+        return null;
+    }
+
+    /**
+     * @hide
+     */
+    @VisibleForTesting
+    public SparseArray<ImsFeature> getFeatures(int slotId) {
+        return mFeaturesBySlot.get(slotId);
+    }
+
+    private IImsMMTelFeature createEmergencyMMTelFeatureInternal(int slotId,
+            IImsFeatureStatusCallback c) {
+        MMTelFeature f = onCreateEmergencyMMTelImsFeature(slotId);
+        if (f != null) {
+            setupFeature(f, slotId, ImsFeature.EMERGENCY_MMTEL, c);
+            return f.getBinder();
+        } else {
+            return null;
+        }
+    }
+
+    private IImsMMTelFeature createMMTelFeatureInternal(int slotId,
+            IImsFeatureStatusCallback c) {
+        MMTelFeature f = onCreateMMTelImsFeature(slotId);
+        if (f != null) {
+            setupFeature(f, slotId, ImsFeature.MMTEL, c);
+            return f.getBinder();
+        } else {
+            return null;
+        }
+    }
+
+    private IImsRcsFeature createRcsFeatureInternal(int slotId,
+            IImsFeatureStatusCallback c) {
+        RcsFeature f = onCreateRcsFeature(slotId);
+        if (f != null) {
+            setupFeature(f, slotId, ImsFeature.RCS, c);
+            return f.getBinder();
+        } else {
+            return null;
+        }
+    }
+
+    private void setupFeature(ImsFeature f, int slotId, int featureType,
+            IImsFeatureStatusCallback c) {
+        f.setContext(this);
+        f.setSlotId(slotId);
+        f.addImsFeatureStatusCallback(c);
+        addImsFeature(slotId, featureType, f);
+        // TODO: Remove once new onFeatureReady AIDL is merged in.
+        f.onFeatureReady();
+    }
+
+    private void addImsFeature(int slotId, int featureType, ImsFeature f) {
+        synchronized (mFeaturesBySlot) {
+            // Get SparseArray for Features, by querying slot Id
+            SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
+            if (features == null) {
+                // Populate new SparseArray of features if it doesn't exist for this slot yet.
+                features = new SparseArray<>();
+                mFeaturesBySlot.put(slotId, features);
+            }
+            features.put(featureType, f);
+        }
+    }
+
+    private void removeImsFeature(int slotId, int featureType,
+            IImsFeatureStatusCallback c) {
+        synchronized (mFeaturesBySlot) {
+            // get ImsFeature associated with the slot/feature
+            SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
+            if (features == null) {
+                Log.w(LOG_TAG, "Can not remove ImsFeature. No ImsFeatures exist on slot "
+                        + slotId);
+                return;
+            }
+            ImsFeature f = features.get(featureType);
+            if (f == null) {
+                Log.w(LOG_TAG, "Can not remove ImsFeature. No feature with type "
+                        + featureType + " exists on slot " + slotId);
+                return;
+            }
+            f.removeImsFeatureStatusCallback(c);
+            f.onFeatureRemoved();
+            features.remove(featureType);
+        }
+    }
+
+    /**
+     * @return An implementation of MMTelFeature that will be used by the system for MMTel
+     * functionality. Must be able to handle emergency calls at any time as well.
+     * @hide
+     */
+    public @Nullable MMTelFeature onCreateEmergencyMMTelImsFeature(int slotId) {
+        return null;
+    }
+
+    /**
+     * @return An implementation of MMTelFeature that will be used by the system for MMTel
+     * functionality.
+     * @hide
+     */
+    public @Nullable MMTelFeature onCreateMMTelImsFeature(int slotId) {
+        return null;
+    }
+
+    /**
+     * @return An implementation of RcsFeature that will be used by the system for RCS.
+     * @hide
+     */
+    public @Nullable RcsFeature onCreateRcsFeature(int slotId) {
+        return null;
+    }
+}
diff --git a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
new file mode 100644
index 0000000..0a12cae
--- /dev/null
+++ b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
@@ -0,0 +1,202 @@
+/*
+ * 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.compat.feature;
+
+import android.annotation.IntDef;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.telephony.SubscriptionManager;
+import android.util.Log;
+
+import com.android.ims.internal.IImsFeatureStatusCallback;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+/**
+ * Base class for all IMS features that are supported by the framework.
+ * @hide
+ */
+public abstract class ImsFeature {
+
+    private static final String LOG_TAG = "ImsFeature";
+
+    /**
+     * Action to broadcast when ImsService is up.
+     * Internal use only.
+     * Only defined here separately compatibility purposes with the old ImsService.
+     * @hide
+     */
+    public static final String ACTION_IMS_SERVICE_UP =
+            "com.android.ims.IMS_SERVICE_UP";
+
+    /**
+     * Action to broadcast when ImsService is down.
+     * Internal use only.
+     * Only defined here separately for compatibility purposes with the old ImsService.
+     * @hide
+     */
+    public static final String ACTION_IMS_SERVICE_DOWN =
+            "com.android.ims.IMS_SERVICE_DOWN";
+
+    /**
+     * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
+     * A long value; the phone ID corresponding to the IMS service coming up or down.
+     * Only defined here separately for compatibility purposes with the old ImsService.
+     * @hide
+     */
+    public static final String EXTRA_PHONE_ID = "android:phone_id";
+
+    // Invalid feature value
+    public static final int INVALID = -1;
+    // ImsFeatures that are defined in the Manifests. Ensure that these values match the previously
+    // defined values in ImsServiceClass for compatibility purposes.
+    public static final int EMERGENCY_MMTEL = 0;
+    public static final int MMTEL = 1;
+    public static final int RCS = 2;
+    // Total number of features defined
+    public static final int MAX = 3;
+
+    // Integer values defining the state of the ImsFeature at any time.
+    @IntDef(flag = true,
+            value = {
+                    STATE_NOT_AVAILABLE,
+                    STATE_INITIALIZING,
+                    STATE_READY,
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ImsState {}
+    public static final int STATE_NOT_AVAILABLE = 0;
+    public static final int STATE_INITIALIZING = 1;
+    public static final int STATE_READY = 2;
+
+    private final Set<IImsFeatureStatusCallback> mStatusCallbacks = Collections.newSetFromMap(
+            new WeakHashMap<IImsFeatureStatusCallback, Boolean>());
+    private @ImsState int mState = STATE_NOT_AVAILABLE;
+    private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+    protected Context mContext;
+
+    public void setContext(Context context) {
+        mContext = context;
+    }
+
+    public void setSlotId(int slotId) {
+        mSlotId = slotId;
+    }
+
+    public int getFeatureState() {
+        return mState;
+    }
+
+    protected final void setFeatureState(@ImsState int state) {
+        if (mState != state) {
+            mState = state;
+            notifyFeatureState(state);
+        }
+    }
+
+    public void addImsFeatureStatusCallback(IImsFeatureStatusCallback c) {
+        if (c == null) {
+            return;
+        }
+        try {
+            // If we have just connected, send queued status.
+            c.notifyImsFeatureStatus(mState);
+            // Add the callback if the callback completes successfully without a RemoteException.
+            synchronized (mStatusCallbacks) {
+                mStatusCallbacks.add(c);
+            }
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage());
+        }
+    }
+
+    public void removeImsFeatureStatusCallback(IImsFeatureStatusCallback c) {
+        if (c == null) {
+            return;
+        }
+        synchronized (mStatusCallbacks) {
+            mStatusCallbacks.remove(c);
+        }
+    }
+
+    /**
+     * Internal method called by ImsFeature when setFeatureState has changed.
+     * @param state
+     */
+    private void notifyFeatureState(@ImsState int state) {
+        synchronized (mStatusCallbacks) {
+            for (Iterator<IImsFeatureStatusCallback> iter = mStatusCallbacks.iterator();
+                 iter.hasNext(); ) {
+                IImsFeatureStatusCallback callback = iter.next();
+                try {
+                    Log.i(LOG_TAG, "notifying ImsFeatureState=" + state);
+                    callback.notifyImsFeatureStatus(state);
+                } catch (RemoteException e) {
+                    // remove if the callback is no longer alive.
+                    iter.remove();
+                    Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage());
+                }
+            }
+        }
+        sendImsServiceIntent(state);
+    }
+
+    /**
+     * Provide backwards compatibility using deprecated service UP/DOWN intents.
+     */
+    private void sendImsServiceIntent(@ImsState int state) {
+        if(mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+            return;
+        }
+        Intent intent;
+        switch (state) {
+            case ImsFeature.STATE_NOT_AVAILABLE:
+            case ImsFeature.STATE_INITIALIZING:
+                intent = new Intent(ACTION_IMS_SERVICE_DOWN);
+                break;
+            case ImsFeature.STATE_READY:
+                intent = new Intent(ACTION_IMS_SERVICE_UP);
+                break;
+            default:
+                intent = new Intent(ACTION_IMS_SERVICE_DOWN);
+        }
+        intent.putExtra(EXTRA_PHONE_ID, mSlotId);
+        mContext.sendBroadcast(intent);
+    }
+
+    /**
+     * Called when the feature is ready to use.
+     */
+    public abstract void onFeatureReady();
+
+    /**
+     * Called when the feature is being removed and must be cleaned up.
+     */
+    public abstract void onFeatureRemoved();
+
+    /**
+     * @return Binder instance
+     */
+    public abstract IInterface getBinder();
+}
diff --git a/telephony/java/android/telephony/ims/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
similarity index 77%
rename from telephony/java/android/telephony/ims/feature/MMTelFeature.java
rename to telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
index 93c316f..d3d17f4 100644
--- a/telephony/java/android/telephony/ims/feature/MMTelFeature.java
+++ b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,14 +14,13 @@
  * limitations under the License
  */
 
-package android.telephony.ims.feature;
+package android.telephony.ims.compat.feature;
 
 import android.app.PendingIntent;
 import android.os.Message;
 import android.os.RemoteException;
-import android.telephony.ims.internal.stub.SmsImplBase;
 
-import com.android.ims.ImsCallProfile;
+import android.telephony.ims.ImsCallProfile;
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsCallSessionListener;
 import com.android.ims.internal.IImsConfig;
@@ -29,9 +28,12 @@
 import com.android.ims.internal.IImsMMTelFeature;
 import com.android.ims.internal.IImsMultiEndpoint;
 import com.android.ims.internal.IImsRegistrationListener;
-import com.android.ims.internal.IImsSmsListener;
 import com.android.ims.internal.IImsUt;
-import com.android.ims.internal.ImsCallSession;
+import android.telephony.ims.ImsCallSession;
+import android.telephony.ims.compat.stub.ImsCallSessionImplBase;
+import android.telephony.ims.stub.ImsEcbmImplBase;
+import android.telephony.ims.stub.ImsMultiEndpointImplBase;
+import android.telephony.ims.stub.ImsUtImplBase;
 
 /**
  * Base implementation for MMTel.
@@ -110,10 +112,10 @@
         }
 
         @Override
-        public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile,
-                IImsCallSessionListener listener) throws RemoteException {
+        public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile)
+                throws RemoteException {
             synchronized (mLock) {
-                return MMTelFeature.this.createCallSession(sessionId, profile, listener);
+                return MMTelFeature.this.createCallSession(sessionId, profile, null);
             }
         }
 
@@ -128,7 +130,8 @@
         @Override
         public IImsUt getUtInterface() throws RemoteException {
             synchronized (mLock) {
-                return MMTelFeature.this.getUtInterface();
+                ImsUtImplBase implBase = MMTelFeature.this.getUtInterface();
+                return implBase != null ? implBase.getInterface() : null;
             }
         }
 
@@ -156,7 +159,8 @@
         @Override
         public IImsEcbm getEcbmInterface() throws RemoteException {
             synchronized (mLock) {
-                return MMTelFeature.this.getEcbmInterface();
+                ImsEcbmImplBase implBase = MMTelFeature.this.getEcbmInterface();
+                return implBase != null ? implBase.getImsEcbm() : null;
             }
         }
 
@@ -170,50 +174,8 @@
         @Override
         public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
             synchronized (mLock) {
-                return MMTelFeature.this.getMultiEndpointInterface();
-            }
-        }
-
-        @Override
-        public void setSmsListener(IImsSmsListener l) throws RemoteException {
-            synchronized (mLock) {
-                MMTelFeature.this.setSmsListener(l);
-            }
-        }
-
-        @Override
-        public void sendSms(int token, int messageRef, String format, String smsc, boolean retry,
-                byte[] pdu) {
-            synchronized (mLock) {
-                MMTelFeature.this.sendSms(token, messageRef, format, smsc, retry, pdu);
-            }
-        }
-
-        @Override
-        public void acknowledgeSms(int token, int messageRef, int result) {
-            synchronized (mLock) {
-                MMTelFeature.this.acknowledgeSms(token, messageRef, result);
-            }
-        }
-
-        @Override
-        public void acknowledgeSmsReport(int token, int messageRef, int result) {
-            synchronized (mLock) {
-                MMTelFeature.this.acknowledgeSmsReport(token, messageRef, result);
-            }
-        }
-
-        @Override
-        public String getSmsFormat() {
-            synchronized (mLock) {
-                return MMTelFeature.this.getSmsFormat();
-            }
-        }
-
-        @Override
-        public void onSmsReady() {
-            synchronized (mLock) {
-                MMTelFeature.this.onSmsReady();
+                ImsMultiEndpointImplBase implBase = MMTelFeature.this.getMultiEndpointInterface();
+                return implBase != null ? implBase.getIImsMultiEndpoint() : null;
             }
         }
     };
@@ -326,7 +288,6 @@
      *
      * @param sessionId a session id which is obtained from {@link #startSession}
      * @param profile a call profile to make the call
-     * @param listener An implementation of IImsCallSessionListener.
      */
     public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile,
             IImsCallSessionListener listener) {
@@ -346,7 +307,7 @@
     /**
      * @return The Ut interface for the supplementary service configuration.
      */
-    public IImsUt getUtInterface() {
+    public ImsUtImplBase getUtInterface() {
         return null;
     }
 
@@ -372,7 +333,7 @@
     /**
      * @return The Emergency call-back mode interface for emergency VoLTE calls that support it.
      */
-    public IImsEcbm getEcbmInterface() {
+    public ImsEcbmImplBase getEcbmInterface() {
         return null;
     }
 
@@ -387,47 +348,10 @@
     /**
      * @return MultiEndpoint interface for DEP notifications
      */
-    public IImsMultiEndpoint getMultiEndpointInterface() {
+    public ImsMultiEndpointImplBase getMultiEndpointInterface() {
         return null;
     }
 
-    private void setSmsListener(IImsSmsListener listener) {
-        getSmsImplementation().registerSmsListener(listener);
-    }
-
-    private void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
-            byte[] pdu) {
-        getSmsImplementation().sendSms(token, messageRef, format, smsc, isRetry, pdu);
-    }
-
-    private void acknowledgeSms(int token, int messageRef,
-            @SmsImplBase.DeliverStatusResult int result) {
-        getSmsImplementation().acknowledgeSms(token, messageRef, result);
-    }
-
-    private void acknowledgeSmsReport(int token, int messageRef,
-            @SmsImplBase.StatusReportResult int result) {
-        getSmsImplementation().acknowledgeSmsReport(token, messageRef, result);
-    }
-
-    private void onSmsReady() {
-        getSmsImplementation().onReady();
-    }
-
-    /**
-     * Must be overridden by IMS Provider to be able to support SMS over IMS. Otherwise a default
-     * non-functional implementation is returned.
-     *
-     * @return an instance of {@link SmsImplBase} which should be implemented by the IMS Provider.
-     */
-    protected SmsImplBase getSmsImplementation() {
-        return new SmsImplBase();
-    }
-
-    public String getSmsFormat() {
-        return getSmsImplementation().getSmsFormat();
-    }
-
     @Override
     public void onFeatureReady() {
 
diff --git a/telephony/java/android/telephony/ims/internal/feature/RcsFeature.java b/telephony/java/android/telephony/ims/compat/feature/RcsFeature.java
similarity index 76%
rename from telephony/java/android/telephony/ims/internal/feature/RcsFeature.java
rename to telephony/java/android/telephony/ims/compat/feature/RcsFeature.java
index 8d1bd9d..228b330 100644
--- a/telephony/java/android/telephony/ims/internal/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/compat/feature/RcsFeature.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,9 +14,10 @@
  * limitations under the License
  */
 
-package android.telephony.ims.internal.feature;
+package android.telephony.ims.compat.feature;
 
-import android.telephony.ims.internal.aidl.IImsRcsFeature;
+
+import com.android.ims.internal.IImsRcsFeature;
 
 /**
  * Base implementation of the RcsFeature APIs. Any ImsService wishing to support RCS should extend
@@ -36,9 +37,8 @@
     }
 
     @Override
-    public void changeEnabledCapabilities(CapabilityChangeRequest request,
-            CapabilityCallbackProxy c) {
-        // Do nothing for base implementation.
+    public void onFeatureReady() {
+
     }
 
     @Override
@@ -46,12 +46,6 @@
 
     }
 
-    /**{@inheritDoc}*/
-    @Override
-    public void onFeatureReady() {
-
-    }
-
     @Override
     public final IImsRcsFeature getBinder() {
         return mImsRcsBinder;
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
new file mode 100644
index 0000000..00cb1e2
--- /dev/null
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
@@ -0,0 +1,585 @@
+/*
+ * 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.compat.stub;
+
+import android.os.Message;
+import android.os.RemoteException;
+
+import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsConferenceState;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsStreamMediaProfile;
+import android.telephony.ims.ImsSuppServiceNotification;
+import android.telephony.ims.aidl.IImsCallSessionListener;
+import com.android.ims.internal.IImsCallSession;
+import com.android.ims.internal.IImsVideoCallProvider;
+
+import android.telephony.ims.ImsCallSession;
+
+/**
+ * Compat implementation of ImsCallSessionImplBase for older implementations.
+ *
+ * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+ * will break other implementations of ImsCallSession maintained by other ImsServices.
+ *
+ * @hide
+ */
+
+public class ImsCallSessionImplBase extends IImsCallSession.Stub {
+
+    @Override
+    // convert to old implementation of listener
+    public final void setListener(IImsCallSessionListener listener)
+            throws RemoteException {
+        setListener(new ImsCallSessionListenerConverter(listener));
+    }
+
+    /**
+     * Sets the listener to listen to the session events. An {@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
+     */
+    public void setListener(com.android.ims.internal.IImsCallSessionListener listener) {
+
+    }
+
+    /**
+     * Closes the object. This {@link ImsCallSessionImplBase} is not usable after being closed.
+     */
+    @Override
+    public void close() {
+
+    }
+
+    /**
+     * @return A String containing the unique call ID of this {@link ImsCallSessionImplBase}.
+     */
+    @Override
+    public String getCallId() {
+        return null;
+    }
+
+    /**
+     * @return The {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is associated
+     * with.
+     */
+    @Override
+    public ImsCallProfile getCallProfile() {
+        return null;
+    }
+
+    /**
+     * @return The local {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is
+     * associated with.
+     */
+    @Override
+    public ImsCallProfile getLocalCallProfile() {
+        return null;
+    }
+
+    /**
+     * @return The remote {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is
+     * associated with.
+     */
+    @Override
+    public ImsCallProfile getRemoteCallProfile() {
+        return null;
+    }
+
+    /**
+     * @param name The String extra key.
+     * @return The string extra value associated with the specified property.
+     */
+    @Override
+    public String getProperty(String name) {
+        return null;
+    }
+
+    /**
+     * @return The {@link ImsCallSessionImplBase} state.
+     */
+    @Override
+    public int getState() {
+        return -1;
+    }
+
+    /**
+     * @return true if the {@link ImsCallSessionImplBase} is in a call, false otherwise.
+     */
+    @Override
+    public boolean isInCall() {
+        return false;
+    }
+
+    /**
+     * Mutes or unmutes the mic for the active call.
+     *
+     * @param muted true if the call should be muted, false otherwise.
+     */
+    @Override
+    public void setMute(boolean muted) {
+    }
+
+    /**
+     * Initiates an IMS call with the specified number and call profile.
+     * The session listener set in {@link #setListener(IImsCallSessionListener)} is called back upon
+     * defined session events.
+     * 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 {@link ImsCallSession.Listener#callSessionStarted},
+     * {@link ImsCallSession.Listener#callSessionStartFailed}
+     */
+    @Override
+    public void start(String callee, ImsCallProfile profile) {
+    }
+
+    /**
+     * Initiates an IMS call with the specified participants and call profile.
+     * The session listener set in {@link #setListener(IImsCallSessionListener)} 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 {@link ImsCallSession.Listener#callSessionStarted},
+     * {@link ImsCallSession.Listener#callSessionStartFailed}
+     */
+    @Override
+    public void startConference(String[] participants, ImsCallProfile profile) {
+    }
+
+    /**
+     * 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 {@link ImsCallSession.Listener#callSessionStarted}
+     */
+    @Override
+    public void accept(int callType, ImsStreamMediaProfile profile) {
+    }
+
+    /**
+     * Rejects an incoming call or session update.
+     *
+     * @param reason reason code to reject an incoming call, defined in {@link ImsReasonInfo}.
+     * {@link ImsCallSession.Listener#callSessionStartFailed}
+     */
+    @Override
+    public void reject(int reason) {
+    }
+
+    /**
+     * Terminates a call.
+     *
+     * @param reason reason code to terminate a call, defined in {@link ImsReasonInfo}.
+     *
+     * @see {@link ImsCallSession.Listener#callSessionTerminated}
+     */
+    @Override
+    public void terminate(int reason) {
+    }
+
+    /**
+     * Puts a call on hold. When it succeeds, {@link ImsCallSession.Listener#callSessionHeld} is
+     * called.
+     *
+     * @param profile stream media profile {@link ImsStreamMediaProfile} to hold the call
+     * @see {@link ImsCallSession.Listener#callSessionHeld},
+     * {@link ImsCallSession.Listener#callSessionHoldFailed}
+     */
+    @Override
+    public void hold(ImsStreamMediaProfile profile) {
+    }
+
+    /**
+     * Continues a call that's on hold. When it succeeds,
+     * {@link ImsCallSession.Listener#callSessionResumed} is called.
+     *
+     * @param profile stream media profile with {@link ImsStreamMediaProfile} to resume the call
+     * @see {@link ImsCallSession.Listener#callSessionResumed},
+     * {@link ImsCallSession.Listener#callSessionResumeFailed}
+     */
+    @Override
+    public void resume(ImsStreamMediaProfile profile) {
+    }
+
+    /**
+     * Merges the active and held call. When the merge starts,
+     * {@link ImsCallSession.Listener#callSessionMergeStarted} is called.
+     * {@link ImsCallSession.Listener#callSessionMergeComplete} is called if the merge is
+     * successful, and {@link ImsCallSession.Listener#callSessionMergeFailed} is called if the merge
+     * fails.
+     *
+     * @see {@link ImsCallSession.Listener#callSessionMergeStarted},
+     * {@link ImsCallSession.Listener#callSessionMergeComplete},
+     *      {@link ImsCallSession.Listener#callSessionMergeFailed}
+     */
+    @Override
+    public void merge() {
+    }
+
+    /**
+     * 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 {@link ImsCallSession.Listener#callSessionUpdated},
+     * {@link ImsCallSession.Listener#callSessionUpdateFailed}
+     */
+    @Override
+    public void update(int callType, ImsStreamMediaProfile profile) {
+    }
+
+    /**
+     * Extends this call to the conference call with the specified recipients.
+     *
+     * @param participants participant list to be invited to the conference call after extending the
+     * call
+     * @see {@link ImsCallSession.Listener#callSessionConferenceExtended},
+     * {@link ImsCallSession.Listener#callSessionConferenceExtendFailed}
+     */
+    @Override
+    public void extendToConference(String[] participants) {
+    }
+
+    /**
+     * Requests the conference server to invite an additional participants to the conference.
+     *
+     * @param participants participant list to be invited to the conference call
+     * @see {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestDelivered},
+     *      {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestFailed}
+     */
+    @Override
+    public void inviteParticipants(String[] participants) {
+    }
+
+    /**
+     * Requests the conference server to remove the specified participants from the conference.
+     *
+     * @param participants participant list to be removed from the conference call
+     * @see {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestDelivered},
+     *      {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestFailed}
+     */
+    @Override
+    public void removeParticipants(String[] participants) {
+    }
+
+    /**
+     * 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.
+     */
+    @Override
+    public void sendDtmf(char c, Message result) {
+    }
+
+    /**
+     * Start 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.
+     */
+    @Override
+    public void startDtmf(char c) {
+    }
+
+    /**
+     * Stop a DTMF code.
+     */
+    @Override
+    public void stopDtmf() {
+    }
+
+    /**
+     * Sends an USSD message.
+     *
+     * @param ussdMessage USSD message to send
+     */
+    @Override
+    public void sendUssd(String ussdMessage) {
+    }
+
+    @Override
+    public IImsVideoCallProvider getVideoCallProvider() {
+        return null;
+    }
+
+    /**
+     * Determines if the current session is multiparty.
+     * @return {@code True} if the session is multiparty.
+     */
+    @Override
+    public boolean isMultiparty() {
+        return false;
+    }
+
+    /**
+     * Device issues RTT modify request
+     * @param toProfile The profile with requested changes made
+     */
+    @Override
+    public void sendRttModifyRequest(ImsCallProfile toProfile) {
+    }
+
+    /**
+     * Device responds to Remote RTT modify request
+     * @param status true if the the request was accepted or false of the request is defined.
+     */
+    @Override
+    public void sendRttModifyResponse(boolean status) {
+    }
+
+    /**
+     * Device sends RTT message
+     * @param rttMessage RTT message to be sent
+     */
+    @Override
+    public void sendRttMessage(String rttMessage) {
+    }
+
+    /**
+     * There are two different ImsCallSessionListeners that need to reconciled here, we need to
+     * convert the "old" version of the com.android.ims.internal.IImsCallSessionListener to the
+     * "new" version of the Listener android.telephony.ims.ImsCallSessionListener when calling
+     * back to the framework.
+     */
+    private class ImsCallSessionListenerConverter
+            extends com.android.ims.internal.IImsCallSessionListener.Stub {
+
+        private final IImsCallSessionListener mNewListener;
+
+        public ImsCallSessionListenerConverter(IImsCallSessionListener listener) {
+            mNewListener = listener;
+        }
+
+        @Override
+        public void callSessionProgressing(IImsCallSession i,
+                ImsStreamMediaProfile imsStreamMediaProfile) throws RemoteException {
+            mNewListener.callSessionProgressing(imsStreamMediaProfile);
+        }
+
+        @Override
+        public void callSessionStarted(IImsCallSession i, ImsCallProfile imsCallProfile)
+                throws RemoteException {
+            mNewListener.callSessionInitiated(imsCallProfile);
+        }
+
+        @Override
+        public void callSessionStartFailed(IImsCallSession i, ImsReasonInfo imsReasonInfo)
+                throws RemoteException {
+            mNewListener.callSessionInitiatedFailed(imsReasonInfo);
+        }
+
+        @Override
+        public void callSessionTerminated(IImsCallSession i, ImsReasonInfo imsReasonInfo)
+                throws RemoteException {
+            mNewListener.callSessionTerminated(imsReasonInfo);
+        }
+
+        @Override
+        public void callSessionHeld(IImsCallSession i, ImsCallProfile imsCallProfile)
+                throws RemoteException {
+            mNewListener.callSessionHeld(imsCallProfile);
+        }
+
+        @Override
+        public void callSessionHoldFailed(IImsCallSession i, ImsReasonInfo imsReasonInfo)
+                throws RemoteException {
+            mNewListener.callSessionHoldFailed(imsReasonInfo);
+        }
+
+        @Override
+        public void callSessionHoldReceived(IImsCallSession i, ImsCallProfile imsCallProfile)
+                throws RemoteException {
+            mNewListener.callSessionHoldReceived(imsCallProfile);
+        }
+
+        @Override
+        public void callSessionResumed(IImsCallSession i, ImsCallProfile imsCallProfile)
+                throws RemoteException {
+            mNewListener.callSessionResumed(imsCallProfile);
+        }
+
+        @Override
+        public void callSessionResumeFailed(IImsCallSession i, ImsReasonInfo imsReasonInfo)
+                throws RemoteException {
+            mNewListener.callSessionResumeFailed(imsReasonInfo);
+        }
+
+        @Override
+        public void callSessionResumeReceived(IImsCallSession i, ImsCallProfile imsCallProfile)
+                throws RemoteException {
+            mNewListener.callSessionResumeReceived(imsCallProfile);
+        }
+
+        @Override
+        public void callSessionMergeStarted(IImsCallSession i, IImsCallSession newSession,
+                ImsCallProfile profile)
+                throws RemoteException {
+            mNewListener.callSessionMergeStarted(newSession, profile);
+        }
+
+        @Override
+        public void callSessionMergeComplete(IImsCallSession iImsCallSession)
+                throws RemoteException {
+            mNewListener.callSessionMergeComplete(iImsCallSession);
+        }
+
+        @Override
+        public void callSessionMergeFailed(IImsCallSession i, ImsReasonInfo imsReasonInfo)
+                throws RemoteException {
+            mNewListener.callSessionMergeFailed(imsReasonInfo);
+        }
+
+        @Override
+        public void callSessionUpdated(IImsCallSession i, ImsCallProfile imsCallProfile)
+                throws RemoteException {
+            mNewListener.callSessionUpdated(imsCallProfile);
+        }
+
+        @Override
+        public void callSessionUpdateFailed(IImsCallSession i, ImsReasonInfo imsReasonInfo)
+                throws RemoteException {
+            mNewListener.callSessionUpdateFailed(imsReasonInfo);
+        }
+
+        @Override
+        public void callSessionUpdateReceived(IImsCallSession i, ImsCallProfile imsCallProfile)
+                throws RemoteException {
+            mNewListener.callSessionUpdateReceived(imsCallProfile);
+        }
+
+        @Override
+        public void callSessionConferenceExtended(IImsCallSession i, IImsCallSession newSession,
+                ImsCallProfile imsCallProfile) throws RemoteException {
+            mNewListener.callSessionConferenceExtended(newSession, imsCallProfile);
+        }
+
+        @Override
+        public void callSessionConferenceExtendFailed(IImsCallSession i,
+                ImsReasonInfo imsReasonInfo) throws RemoteException {
+            mNewListener.callSessionConferenceExtendFailed(imsReasonInfo);
+        }
+
+        @Override
+        public void callSessionConferenceExtendReceived(IImsCallSession i,
+                IImsCallSession newSession, ImsCallProfile imsCallProfile)
+                throws RemoteException {
+            mNewListener.callSessionConferenceExtendReceived(newSession, imsCallProfile);
+        }
+
+        @Override
+        public void callSessionInviteParticipantsRequestDelivered(IImsCallSession i)
+                throws RemoteException {
+            mNewListener.callSessionInviteParticipantsRequestDelivered();
+        }
+
+        @Override
+        public void callSessionInviteParticipantsRequestFailed(IImsCallSession i,
+                ImsReasonInfo imsReasonInfo) throws RemoteException {
+            mNewListener.callSessionInviteParticipantsRequestFailed(imsReasonInfo);
+        }
+
+        @Override
+        public void callSessionRemoveParticipantsRequestDelivered(IImsCallSession i)
+                throws RemoteException {
+            mNewListener.callSessionRemoveParticipantsRequestDelivered();
+        }
+
+        @Override
+        public void callSessionRemoveParticipantsRequestFailed(IImsCallSession i,
+                ImsReasonInfo imsReasonInfo) throws RemoteException {
+            mNewListener.callSessionRemoveParticipantsRequestFailed(imsReasonInfo);
+        }
+
+        @Override
+        public void callSessionConferenceStateUpdated(IImsCallSession i,
+                ImsConferenceState imsConferenceState) throws RemoteException {
+            mNewListener.callSessionConferenceStateUpdated(imsConferenceState);
+        }
+
+        @Override
+        public void callSessionUssdMessageReceived(IImsCallSession i, int mode, String message)
+                throws RemoteException {
+            mNewListener.callSessionUssdMessageReceived(mode, message);
+        }
+
+        @Override
+        public void callSessionHandover(IImsCallSession i, int srcAccessTech, int targetAccessTech,
+                ImsReasonInfo reasonInfo) throws RemoteException {
+            mNewListener.callSessionHandover(srcAccessTech, targetAccessTech, reasonInfo);
+        }
+
+        @Override
+        public void callSessionHandoverFailed(IImsCallSession i, int srcAccessTech,
+                int targetAccessTech, ImsReasonInfo reasonInfo) throws RemoteException {
+            mNewListener.callSessionHandoverFailed(srcAccessTech, targetAccessTech, reasonInfo);
+        }
+
+        @Override
+        public void callSessionMayHandover(IImsCallSession i, int srcAccessTech, int targetAccessTech)
+                throws RemoteException {
+            mNewListener.callSessionMayHandover(srcAccessTech, targetAccessTech);
+        }
+
+        @Override
+        public void callSessionTtyModeReceived(IImsCallSession iImsCallSession, int mode)
+                throws RemoteException {
+            mNewListener.callSessionTtyModeReceived(mode);
+        }
+
+        @Override
+        public void callSessionMultipartyStateChanged(IImsCallSession i, boolean isMultiparty)
+                throws RemoteException {
+            mNewListener.callSessionMultipartyStateChanged(isMultiparty);
+        }
+
+        @Override
+        public void callSessionSuppServiceReceived(IImsCallSession i,
+                ImsSuppServiceNotification imsSuppServiceNotification) throws RemoteException {
+            mNewListener.callSessionSuppServiceReceived(imsSuppServiceNotification);
+        }
+
+        @Override
+        public void callSessionRttModifyRequestReceived(IImsCallSession i,
+                ImsCallProfile imsCallProfile) throws RemoteException {
+            mNewListener.callSessionRttModifyRequestReceived(imsCallProfile);
+        }
+
+        @Override
+        public void callSessionRttModifyResponseReceived(int status) throws RemoteException {
+            mNewListener.callSessionRttModifyResponseReceived(status);
+        }
+
+        @Override
+        public void callSessionRttMessageReceived(String rttMessage) throws RemoteException {
+            mNewListener.callSessionRttMessageReceived(rttMessage);
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
new file mode 100644
index 0000000..2c325ba8
--- /dev/null
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2017 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.compat.stub;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsConfigListener;
+import com.android.ims.internal.IImsConfig;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+
+
+/**
+ * Base implementation of ImsConfig.
+ * Override the methods that your implementation of ImsConfig supports.
+ *
+ * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+ * will break other implementations of ImsConfig maintained by other ImsServices.
+ *
+ * Provides APIs to get/set the IMS service feature/capability/parameters.
+ * The config items include:
+ * 1) Items provisioned by the operator.
+ * 2) Items configured by user. Mainly service feature class.
+ *
+ * The inner class {@link ImsConfigStub} implements methods of IImsConfig AIDL interface.
+ * The IImsConfig AIDL interface is called by ImsConfig, which may exist in many other processes.
+ * ImsConfigImpl access to the configuration parameters may be arbitrarily slow, especially in
+ * during initialization, or times when a lot of configuration parameters are being set/get
+ * (such as during boot up or SIM card change). By providing a cache in ImsConfigStub, we can speed
+ * up access to these configuration parameters, so a query to the ImsConfigImpl does not have to be
+ * performed every time.
+ * @hide
+ */
+
+public class ImsConfigImplBase {
+
+    static final private String TAG = "ImsConfigImplBase";
+
+    ImsConfigStub mImsConfigStub;
+
+    public ImsConfigImplBase(Context context) {
+        mImsConfigStub = new ImsConfigStub(this, context);
+    }
+
+    /**
+     * Gets the value for ims service/capabilities parameters from the provisioned
+     * value storage. Synchronous blocking call.
+     *
+     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @return value in Integer format.
+     */
+    public int getProvisionedValue(int item) throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Gets the value for ims service/capabilities parameters from the provisioned
+     * value storage. Synchronous blocking call.
+     *
+     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @return value in String format.
+     */
+    public String getProvisionedStringValue(int item) throws RemoteException {
+        return null;
+    }
+
+    /**
+     * Sets the value for IMS service/capabilities parameters by the operator device
+     * management entity. It sets the config item value in the provisioned storage
+     * from which the master value is derived. Synchronous blocking call.
+     *
+     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @param value in Integer format.
+     * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+     */
+    public int setProvisionedValue(int item, int value) throws RemoteException {
+        return ImsConfig.OperationStatusConstants.FAILED;
+    }
+
+    /**
+     * Sets the value for IMS service/capabilities parameters by the operator device
+     * management entity. It sets the config item value in the provisioned storage
+     * from which the master value is derived.  Synchronous blocking call.
+     *
+     * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @param value in String format.
+     * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+     */
+    public int setProvisionedStringValue(int item, String value) throws RemoteException {
+        return ImsConfig.OperationStatusConstants.FAILED;
+    }
+
+    /**
+     * Gets the value of the specified IMS feature item for specified network type.
+     * This operation gets the feature config value from the master storage (i.e. final
+     * value). Asynchronous non-blocking call.
+     *
+     * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants.
+     * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
+     * @param listener feature value returned asynchronously through listener.
+     */
+    public void getFeatureValue(int feature, int network, ImsConfigListener listener)
+            throws RemoteException {
+    }
+
+    /**
+     * Sets the value for IMS feature item for specified network type.
+     * This operation stores the user setting in setting db from which master db
+     * is derived.
+     *
+     * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants.
+     * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
+     * @param value as defined in com.android.ims.ImsConfig#FeatureValueConstants.
+     * @param listener, provided if caller needs to be notified for set result.
+     */
+    public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener)
+            throws RemoteException {
+    }
+
+    /**
+     * Gets the value for IMS VoLTE provisioned.
+     * This should be the same as the operator provisioned value if applies.
+     */
+    public boolean getVolteProvisioned() throws RemoteException {
+        return false;
+    }
+
+    /**
+     * Gets the value for IMS feature item video quality.
+     *
+     * @param listener Video quality value returned asynchronously through listener.
+     */
+    public void getVideoQuality(ImsConfigListener listener) throws RemoteException {
+    }
+
+    /**
+     * 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.
+     */
+    public void setVideoQuality(int quality, ImsConfigListener listener) throws RemoteException {
+    }
+
+    public IImsConfig getIImsConfig() { return mImsConfigStub; }
+
+    /**
+     * Updates provisioning value and notifies the framework of the change.
+     * Doesn't call #setProvisionedValue and assumes the result succeeded.
+     * This should only be used by modem when they implicitly changed provisioned values.
+     *
+     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @param value in Integer format.
+     */
+    public final void notifyProvisionedValueChanged(int item, int value) {
+        mImsConfigStub.updateCachedValue(item, value, true);
+    }
+
+    /**
+     * Updates provisioning value and notifies the framework of the change.
+     * Doesn't call #setProvisionedValue and assumes the result succeeded.
+     * This should only be used by modem when they implicitly changed provisioned values.
+     *
+     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @param value in String format.
+     */
+    public final void notifyProvisionedValueChanged(int item, String value) {
+        mImsConfigStub.updateCachedValue(item, value, true);
+    }
+
+    /**
+     * Implements the IImsConfig AIDL interface, which is called by potentially many processes
+     * in order to get/set configuration parameters.
+     *
+     * It holds an object of ImsConfigImplBase class which is usually extended by ImsConfigImpl
+     * with actual implementations from vendors. This class caches provisioned values from
+     * ImsConfigImpl layer because queries through ImsConfigImpl can be slow. When query goes in,
+     * it first checks cache layer. If missed, it will call the vendor implementation of
+     * ImsConfigImplBase API.
+     * and cache the return value if the set succeeds.
+     *
+     * Provides APIs to get/set the IMS service feature/capability/parameters.
+     * The config items include:
+     * 1) Items provisioned by the operator.
+     * 2) Items configured by user. Mainly service feature class.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    static public class ImsConfigStub extends IImsConfig.Stub {
+        Context mContext;
+        WeakReference<ImsConfigImplBase> mImsConfigImplBaseWeakReference;
+        private HashMap<Integer, Integer> mProvisionedIntValue = new HashMap<>();
+        private HashMap<Integer, String> mProvisionedStringValue = new HashMap<>();
+
+        @VisibleForTesting
+        public ImsConfigStub(ImsConfigImplBase imsConfigImplBase, Context context) {
+            mContext = context;
+            mImsConfigImplBaseWeakReference =
+                    new WeakReference<ImsConfigImplBase>(imsConfigImplBase);
+        }
+
+        /**
+         * Gets the value for ims service/capabilities parameters. It first checks its local cache,
+         * if missed, it will call ImsConfigImplBase.getProvisionedValue.
+         * Synchronous blocking call.
+         *
+         * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+         * @return value in Integer format.
+         */
+        @Override
+        public synchronized int getProvisionedValue(int item) throws RemoteException {
+            if (mProvisionedIntValue.containsKey(item)) {
+                return mProvisionedIntValue.get(item);
+            } else {
+                int retVal = getImsConfigImpl().getProvisionedValue(item);
+                if (retVal != ImsConfig.OperationStatusConstants.UNKNOWN) {
+                    updateCachedValue(item, retVal, false);
+                }
+                return retVal;
+            }
+        }
+
+        /**
+         * Gets the value for ims service/capabilities parameters. It first checks its local cache,
+         * if missed, it will call #ImsConfigImplBase.getProvisionedValue.
+         * Synchronous blocking call.
+         *
+         * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+         * @return value in String format.
+         */
+        @Override
+        public synchronized String getProvisionedStringValue(int item) throws RemoteException {
+            if (mProvisionedIntValue.containsKey(item)) {
+                return mProvisionedStringValue.get(item);
+            } else {
+                String retVal = getImsConfigImpl().getProvisionedStringValue(item);
+                if (retVal != null) {
+                    updateCachedValue(item, retVal, false);
+                }
+                return retVal;
+            }
+        }
+
+        /**
+         * Sets the value for IMS service/capabilities parameters by the operator device
+         * management entity. It sets the config item value in the provisioned storage
+         * from which the master value is derived, and write it into local cache.
+         * Synchronous blocking call.
+         *
+         * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+         * @param value in Integer format.
+         * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+         */
+        @Override
+        public synchronized int setProvisionedValue(int item, int value) throws RemoteException {
+            mProvisionedIntValue.remove(item);
+            int retVal = getImsConfigImpl().setProvisionedValue(item, value);
+            if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+                updateCachedValue(item, value, true);
+            } else {
+                Log.d(TAG, "Set provision value of " + item +
+                        " to " + value + " failed with error code " + retVal);
+            }
+
+            return retVal;
+        }
+
+        /**
+         * Sets the value for IMS service/capabilities parameters by the operator device
+         * management entity. It sets the config item value in the provisioned storage
+         * from which the master value is derived, and write it into local cache.
+         * Synchronous blocking call.
+         *
+         * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
+         * @param value in String format.
+         * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+         */
+        @Override
+        public synchronized int setProvisionedStringValue(int item, String value)
+                throws RemoteException {
+            mProvisionedStringValue.remove(item);
+            int retVal = getImsConfigImpl().setProvisionedStringValue(item, value);
+            if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+                updateCachedValue(item, value, true);
+            }
+
+            return retVal;
+        }
+
+        /**
+         * Wrapper function to call ImsConfigImplBase.getFeatureValue.
+         */
+        @Override
+        public void getFeatureValue(int feature, int network, ImsConfigListener listener)
+                throws RemoteException {
+            getImsConfigImpl().getFeatureValue(feature, network, listener);
+        }
+
+        /**
+         * Wrapper function to call ImsConfigImplBase.setFeatureValue.
+         */
+        @Override
+        public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener)
+                throws RemoteException {
+            getImsConfigImpl().setFeatureValue(feature, network, value, listener);
+        }
+
+        /**
+         * Wrapper function to call ImsConfigImplBase.getVolteProvisioned.
+         */
+        @Override
+        public boolean getVolteProvisioned() throws RemoteException {
+            return getImsConfigImpl().getVolteProvisioned();
+        }
+
+        /**
+         * Wrapper function to call ImsConfigImplBase.getVideoQuality.
+         */
+        @Override
+        public void getVideoQuality(ImsConfigListener listener) throws RemoteException {
+            getImsConfigImpl().getVideoQuality(listener);
+        }
+
+        /**
+         * Wrapper function to call ImsConfigImplBase.setVideoQuality.
+         */
+        @Override
+        public void setVideoQuality(int quality, ImsConfigListener listener)
+                throws RemoteException {
+            getImsConfigImpl().setVideoQuality(quality, listener);
+        }
+
+        private ImsConfigImplBase getImsConfigImpl() throws RemoteException {
+            ImsConfigImplBase ref = mImsConfigImplBaseWeakReference.get();
+            if (ref == null) {
+                throw new RemoteException("Fail to get ImsConfigImpl");
+            } else {
+                return ref;
+            }
+        }
+
+        private void sendImsConfigChangedIntent(int item, int value) {
+            sendImsConfigChangedIntent(item, Integer.toString(value));
+        }
+
+        private void sendImsConfigChangedIntent(int item, String value) {
+            Intent configChangedIntent = new Intent(ImsConfig.ACTION_IMS_CONFIG_CHANGED);
+            configChangedIntent.putExtra(ImsConfig.EXTRA_CHANGED_ITEM, item);
+            configChangedIntent.putExtra(ImsConfig.EXTRA_NEW_VALUE, value);
+            if (mContext != null) {
+                mContext.sendBroadcast(configChangedIntent);
+            }
+        }
+
+        protected synchronized void updateCachedValue(int item, int value, boolean notifyChange) {
+            mProvisionedIntValue.put(item, value);
+            if (notifyChange) {
+                sendImsConfigChangedIntent(item, value);
+            }
+        }
+
+        protected synchronized void updateCachedValue(
+                int item, String value, boolean notifyChange) {
+            mProvisionedStringValue.put(item, value);
+            if (notifyChange) {
+                sendImsConfigChangedIntent(item, value);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtListenerImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
similarity index 90%
rename from telephony/java/android/telephony/ims/stub/ImsUtListenerImplBase.java
rename to telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
index daa74c8..b2aa080 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtListenerImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,15 +14,15 @@
  * limitations under the License
  */
 
-package android.telephony.ims.stub;
+package android.telephony.ims.compat.stub;
 
 import android.os.Bundle;
 import android.os.RemoteException;
 
-import com.android.ims.ImsCallForwardInfo;
-import com.android.ims.ImsReasonInfo;
-import com.android.ims.ImsSsData;
-import com.android.ims.ImsSsInfo;
+import android.telephony.ims.ImsCallForwardInfo;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsSsData;
+import android.telephony.ims.ImsSsInfo;
 import com.android.ims.internal.IImsUt;
 import com.android.ims.internal.IImsUtListener;
 
diff --git a/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.aidl b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.aidl
similarity index 92%
rename from telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.aidl
rename to telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.aidl
index f4ec0eb..e789bd5 100644
--- a/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.aidl
+++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.aidl
@@ -14,6 +14,6 @@
  * limitations under the License
  */
 
-package android.telephony.ims.internal.feature;
+package android.telephony.ims.feature;
 
 parcelable CapabilityChangeRequest;
diff --git a/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
similarity index 79%
rename from telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.java
rename to telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
index 5dbf077..7c793a5 100644
--- a/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.java
+++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,8 +14,9 @@
  * limitations under the License
  */
 
-package android.telephony.ims.internal.feature;
+package android.telephony.ims.feature;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -30,17 +31,32 @@
  * the request.
  * {@hide}
  */
-public class CapabilityChangeRequest implements Parcelable {
+@SystemApi
+public final class CapabilityChangeRequest implements Parcelable {
 
+    /**
+     * Contains a feature capability, defined as
+     * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE},
+     * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO},
+     * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, or
+     * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS},
+     * along with an associated technology, defined as
+     * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE} or
+     * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN}
+     */
     public static class CapabilityPair {
         private final int mCapability;
         private final int radioTech;
 
-        public CapabilityPair(int capability, int radioTech) {
+        public CapabilityPair(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
+                @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
             this.mCapability = capability;
             this.radioTech = radioTech;
         }
 
+        /**
+         * @hide
+         */
         @Override
         public boolean equals(Object o) {
             if (this == o) return true;
@@ -52,6 +68,9 @@
             return getRadioTech() == that.getRadioTech();
         }
 
+        /**
+         * @hide
+         */
         @Override
         public int hashCode() {
             int result = getCapability();
@@ -59,10 +78,22 @@
             return result;
         }
 
+        /**
+         * @return The stored capability, defined as
+         * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE},
+         * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO},
+         * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, or
+         * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS}
+         */
         public @MmTelFeature.MmTelCapabilities.MmTelCapability int getCapability() {
             return mCapability;
         }
 
+        /**
+         * @return the stored radio technology, defined as
+         * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE} or
+         * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN}
+         */
         public @ImsRegistrationImplBase.ImsRegistrationTech int getRadioTech() {
             return radioTech;
         }
@@ -73,6 +104,7 @@
     // Pair contains <radio tech, mCapability>
     private final Set<CapabilityPair> mCapabilitiesToDisable;
 
+    /** @hide */
     public CapabilityChangeRequest() {
         mCapabilitiesToEnable = new ArraySet<>();
         mCapabilitiesToDisable = new ArraySet<>();
@@ -130,6 +162,9 @@
         }
     }
 
+    /**
+     * @hide
+     */
     protected CapabilityChangeRequest(Parcel in) {
         int enableSize = in.readInt();
         mCapabilitiesToEnable = new ArraySet<>(enableSize);
@@ -177,17 +212,24 @@
         }
     }
 
+    /**
+     * @hide
+     */
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
         if (!(o instanceof CapabilityChangeRequest)) return false;
 
-        CapabilityChangeRequest that = (CapabilityChangeRequest) o;
+        CapabilityChangeRequest
+                that = (CapabilityChangeRequest) o;
 
         if (!mCapabilitiesToEnable.equals(that.mCapabilitiesToEnable)) return false;
         return mCapabilitiesToDisable.equals(that.mCapabilitiesToDisable);
     }
 
+    /**
+     * @hide
+     */
     @Override
     public int hashCode() {
         int result = mCapabilitiesToEnable.hashCode();
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index d47cea30..bfdd453 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -17,28 +17,35 @@
 package android.telephony.ims.feature;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.content.Intent;
 import android.os.IInterface;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.telephony.SubscriptionManager;
+import android.telephony.ims.aidl.IImsCapabilityCallback;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.util.Log;
 
 import com.android.ims.internal.IImsFeatureStatusCallback;
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Set;
 import java.util.WeakHashMap;
 
 /**
- * Base class for all IMS features that are supported by the framework.
+ * Base class for all IMS features that are supported by the framework. Use a concrete subclass
+ * of {@link ImsFeature}, such as {@link MmTelFeature} or {@link RcsFeature}.
+ *
  * @hide
  */
+@SystemApi
 public abstract class ImsFeature {
 
     private static final String LOG_TAG = "ImsFeature";
@@ -46,7 +53,8 @@
     /**
      * Action to broadcast when ImsService is up.
      * Internal use only.
-     * Only defined here separately compatibility purposes with the old ImsService.
+     * Only defined here separately for compatibility purposes with the old ImsService.
+     *
      * @hide
      */
     public static final String ACTION_IMS_SERVICE_UP =
@@ -56,6 +64,7 @@
      * Action to broadcast when ImsService is down.
      * Internal use only.
      * Only defined here separately for compatibility purposes with the old ImsService.
+     *
      * @hide
      */
     public static final String ACTION_IMS_SERVICE_DOWN =
@@ -65,67 +74,329 @@
      * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
      * A long value; the phone ID corresponding to the IMS service coming up or down.
      * Only defined here separately for compatibility purposes with the old ImsService.
+     *
      * @hide
      */
     public static final String EXTRA_PHONE_ID = "android:phone_id";
 
-    // Invalid feature value
-    public static final int INVALID = -1;
+    /**
+     * Invalid feature value\
+     * @hide
+     */
+    public static final int FEATURE_INVALID = -1;
     // ImsFeatures that are defined in the Manifests. Ensure that these values match the previously
     // defined values in ImsServiceClass for compatibility purposes.
-    public static final int EMERGENCY_MMTEL = 0;
-    public static final int MMTEL = 1;
-    public static final int RCS = 2;
-    // Total number of features defined
-    public static final int MAX = 3;
+    /**
+     * This feature supports emergency calling over MMTEL.
+     */
+    public static final int FEATURE_EMERGENCY_MMTEL = 0;
+    /**
+     * This feature supports the MMTEL feature.
+     */
+    public static final int FEATURE_MMTEL = 1;
+    /**
+     * This feature supports the RCS feature.
+     */
+    public static final int FEATURE_RCS = 2;
+    /**
+     * Total number of features defined
+     * @hide
+     */
+    public static final int FEATURE_MAX = 3;
 
-    // Integer values defining the state of the ImsFeature at any time.
+    /**
+     * Integer values defining IMS features that are supported in ImsFeature.
+     * @hide
+     */
     @IntDef(flag = true,
             value = {
-                    STATE_NOT_AVAILABLE,
+                    FEATURE_EMERGENCY_MMTEL,
+                    FEATURE_MMTEL,
+                    FEATURE_RCS
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FeatureType {}
+
+    /**
+     * Integer values defining the state of the ImsFeature at any time.
+     * @hide
+     */
+    @IntDef(flag = true,
+            value = {
+                    STATE_UNAVAILABLE,
                     STATE_INITIALIZING,
                     STATE_READY,
             })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ImsState {}
-    public static final int STATE_NOT_AVAILABLE = 0;
+
+    /**
+     * This {@link ImsFeature}'s state is unavailable and should not be communicated with.
+     */
+    public static final int STATE_UNAVAILABLE = 0;
+    /**
+     * This {@link ImsFeature} state is initializing and should not be communicated with.
+     */
     public static final int STATE_INITIALIZING = 1;
+    /**
+     * This {@link ImsFeature} is ready for communication.
+     */
     public static final int STATE_READY = 2;
 
+    /**
+     * Integer values defining the result codes that should be returned from
+     * {@link #changeEnabledCapabilities} when the framework tries to set a feature's capability.
+     * @hide
+     */
+    @IntDef(flag = true,
+            value = {
+                    CAPABILITY_ERROR_GENERIC,
+                    CAPABILITY_SUCCESS
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ImsCapabilityError {}
+
+    /**
+     * The capability was unable to be changed.
+     */
+    public static final int CAPABILITY_ERROR_GENERIC = -1;
+    /**
+     * The capability was able to be changed.
+     */
+    public static final int CAPABILITY_SUCCESS = 0;
+
+
+    /**
+     * The framework implements this callback in order to register for Feature Capability status
+     * updates, via {@link #onCapabilitiesStatusChanged(Capabilities)}, query Capability
+     * configurations, via {@link #onQueryCapabilityConfiguration}, as well as to receive error
+     * callbacks when the ImsService can not change the capability as requested, via
+     * {@link #onChangeCapabilityConfigurationError}.
+     *
+     * @hide
+     */
+    public static class CapabilityCallback extends IImsCapabilityCallback.Stub {
+
+        @Override
+        public final void onCapabilitiesStatusChanged(int config) throws RemoteException {
+            onCapabilitiesStatusChanged(new Capabilities(config));
+        }
+
+        /**
+         * Returns the result of a query for the capability configuration of a requested capability.
+         *
+         * @param capability The capability that was requested.
+         * @param radioTech The IMS radio technology associated with the capability.
+         * @param isEnabled true if the capability is enabled, false otherwise.
+         */
+        @Override
+        public void onQueryCapabilityConfiguration(int capability, int radioTech,
+                boolean isEnabled) {
+
+        }
+
+        /**
+         * Called when a change to the capability configuration has returned an error.
+         *
+         * @param capability The capability that was requested to be changed.
+         * @param radioTech The IMS radio technology associated with the capability.
+         * @param reason error associated with the failure to change configuration.
+         */
+        @Override
+        public void onChangeCapabilityConfigurationError(int capability, int radioTech,
+                @ImsCapabilityError int reason) {
+        }
+
+        /**
+         * The status of the feature's capabilities has changed to either available or unavailable.
+         * If unavailable, the feature is not able to support the unavailable capability at this
+         * time.
+         *
+         * @param config The new availability of the capabilities.
+         */
+        public void onCapabilitiesStatusChanged(Capabilities config) {
+        }
+    }
+
+    /**
+     * Used by the ImsFeature to call back to the CapabilityCallback that the framework has
+     * provided.
+     */
+    protected static class CapabilityCallbackProxy {
+        private final IImsCapabilityCallback mCallback;
+
+        /** @hide */
+        public CapabilityCallbackProxy(IImsCapabilityCallback c) {
+            mCallback = c;
+        }
+
+        /**
+         * This method notifies the provided framework callback that the request to change the
+         * indicated capability has failed and has not changed.
+         *
+         * @param capability The Capability that will be notified to the framework, defined as
+         * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE},
+         * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO},
+         * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, or
+         * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS}.
+         * @param radioTech The radio tech that this capability failed for, defined as
+         * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE} or
+         * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN}.
+         * @param reason The reason this capability was unable to be changed, defined as
+         * {@link #CAPABILITY_ERROR_GENERIC} or {@link #CAPABILITY_SUCCESS}.
+         */
+        public void onChangeCapabilityConfigurationError(int capability, int radioTech,
+                @ImsCapabilityError int reason) {
+            if (mCallback == null) {
+                return;
+            }
+            try {
+                mCallback.onChangeCapabilityConfigurationError(capability, radioTech, reason);
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "onChangeCapabilityConfigurationError called on dead binder.");
+            }
+        }
+    }
+
+    /**
+     * Contains the capabilities defined and supported by an ImsFeature in the form of a bit mask.
+     * @hide
+     */
+    public static class Capabilities {
+        protected int mCapabilities = 0;
+
+        public Capabilities() {
+        }
+
+        protected Capabilities(int capabilities) {
+            mCapabilities = capabilities;
+        }
+
+        /**
+         * @param capabilities Capabilities to be added to the configuration in the form of a
+         *     bit mask.
+         */
+        public void addCapabilities(int capabilities) {
+            mCapabilities |= capabilities;
+        }
+
+        /**
+         * @param capabilities Capabilities to be removed to the configuration in the form of a
+         *     bit mask.
+         */
+        public void removeCapabilities(int capabilities) {
+            mCapabilities &= ~capabilities;
+        }
+
+        /**
+         * @return true if all of the capabilities specified are capable.
+         */
+        public boolean isCapable(int capabilities) {
+            return (mCapabilities & capabilities) == capabilities;
+        }
+
+        /**
+         * @return a deep copy of the Capabilites.
+         */
+        public Capabilities copy() {
+            return new Capabilities(mCapabilities);
+        }
+
+        /**
+         * @return a bitmask containing the capability flags directly.
+         */
+        public int getMask() {
+            return mCapabilities;
+        }
+
+        /**
+         * @hide
+         */
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof Capabilities)) return false;
+
+            Capabilities that = (Capabilities) o;
+
+            return mCapabilities == that.mCapabilities;
+        }
+
+        /**
+         * @hide
+         */
+        @Override
+        public int hashCode() {
+            return mCapabilities;
+        }
+
+        /**
+         * @hide
+         */
+        @Override
+        public String toString() {
+            return "Capabilities: " + Integer.toBinaryString(mCapabilities);
+        }
+    }
+
     private final Set<IImsFeatureStatusCallback> mStatusCallbacks = Collections.newSetFromMap(
             new WeakHashMap<IImsFeatureStatusCallback, Boolean>());
-    private @ImsState int mState = STATE_NOT_AVAILABLE;
+    private @ImsState int mState = STATE_UNAVAILABLE;
     private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+    /**
+     * @hide
+     */
     protected Context mContext;
+    private final Object mLock = new Object();
+    private final RemoteCallbackList<IImsCapabilityCallback> mCapabilityCallbacks
+            = new RemoteCallbackList<>();
+    private Capabilities mCapabilityStatus = new Capabilities();
 
-    public void setContext(Context context) {
+    /**
+     * @hide
+     */
+    public final void initialize(Context context, int slotId) {
         mContext = context;
-    }
-
-    public void setSlotId(int slotId) {
         mSlotId = slotId;
     }
 
+    /**
+     * @return The current state of the feature, defined as {@link #STATE_UNAVAILABLE},
+     * {@link #STATE_INITIALIZING}, or {@link #STATE_READY}.
+     * @hide
+     */
     public int getFeatureState() {
-        return mState;
-    }
-
-    protected final void setFeatureState(@ImsState int state) {
-        if (mState != state) {
-            mState = state;
-            notifyFeatureState(state);
+        synchronized (mLock) {
+            return mState;
         }
     }
 
-    public void addImsFeatureStatusCallback(IImsFeatureStatusCallback c) {
-        if (c == null) {
-            return;
+    /**
+     * Set the state of the ImsFeature. The state is used as a signal to the framework to start or
+     * stop communication, depending on the state sent.
+     * @param state The ImsFeature's state, defined as {@link #STATE_UNAVAILABLE},
+     * {@link #STATE_INITIALIZING}, or {@link #STATE_READY}.
+     */
+    public final void setFeatureState(@ImsState int state) {
+        synchronized (mLock) {
+            if (mState != state) {
+                mState = state;
+                notifyFeatureState(state);
+            }
         }
+    }
+
+    /**
+     * Not final for testing, but shouldn't be extended!
+     * @hide
+     */
+    @VisibleForTesting
+    public void addImsFeatureStatusCallback(@NonNull IImsFeatureStatusCallback c) {
         try {
             // If we have just connected, send queued status.
-            c.notifyImsFeatureStatus(mState);
+            c.notifyImsFeatureStatus(getFeatureState());
             // Add the callback if the callback completes successfully without a RemoteException.
-            synchronized (mStatusCallbacks) {
+            synchronized (mLock) {
                 mStatusCallbacks.add(c);
             }
         } catch (RemoteException e) {
@@ -133,23 +404,24 @@
         }
     }
 
-    public void removeImsFeatureStatusCallback(IImsFeatureStatusCallback c) {
-        if (c == null) {
-            return;
-        }
-        synchronized (mStatusCallbacks) {
+    /**
+     * Not final for testing, but shouldn't be extended!
+     * @hide
+     */
+    @VisibleForTesting
+    public void removeImsFeatureStatusCallback(@NonNull IImsFeatureStatusCallback c) {
+        synchronized (mLock) {
             mStatusCallbacks.remove(c);
         }
     }
 
     /**
      * Internal method called by ImsFeature when setFeatureState has changed.
-     * @param state
      */
     private void notifyFeatureState(@ImsState int state) {
-        synchronized (mStatusCallbacks) {
+        synchronized (mLock) {
             for (Iterator<IImsFeatureStatusCallback> iter = mStatusCallbacks.iterator();
-                 iter.hasNext(); ) {
+                    iter.hasNext(); ) {
                 IImsFeatureStatusCallback callback = iter.next();
                 try {
                     Log.i(LOG_TAG, "notifying ImsFeatureState=" + state);
@@ -168,12 +440,12 @@
      * Provide backwards compatibility using deprecated service UP/DOWN intents.
      */
     private void sendImsServiceIntent(@ImsState int state) {
-        if(mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+        if (mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
             return;
         }
         Intent intent;
         switch (state) {
-            case ImsFeature.STATE_NOT_AVAILABLE:
+            case ImsFeature.STATE_UNAVAILABLE:
             case ImsFeature.STATE_INITIALIZING:
                 intent = new Intent(ACTION_IMS_SERVICE_DOWN);
                 break;
@@ -188,17 +460,104 @@
     }
 
     /**
-     * Called when the feature is ready to use.
+     * @hide
      */
-    public abstract void onFeatureReady();
+    public final void addCapabilityCallback(IImsCapabilityCallback c) {
+        mCapabilityCallbacks.register(c);
+    }
 
     /**
-     * Called when the feature is being removed and must be cleaned up.
+     * @hide
+     */
+    public final void removeCapabilityCallback(IImsCapabilityCallback c) {
+        mCapabilityCallbacks.unregister(c);
+    }
+
+    /**
+     * @return the cached capabilities status for this feature.
+     * @hide
+     */
+    @VisibleForTesting
+    public Capabilities queryCapabilityStatus() {
+        synchronized (mLock) {
+            return mCapabilityStatus.copy();
+        }
+    }
+
+    /**
+     * Called internally to request the change of enabled capabilities.
+     * @hide
+     */
+    @VisibleForTesting
+    public final void requestChangeEnabledCapabilities(CapabilityChangeRequest request,
+            IImsCapabilityCallback c) {
+        if (request == null) {
+            throw new IllegalArgumentException(
+                    "ImsFeature#requestChangeEnabledCapabilities called with invalid params.");
+        }
+        changeEnabledCapabilities(request, new CapabilityCallbackProxy(c));
+    }
+
+    /**
+     * Called by the ImsFeature when the capabilities status has changed.
+     *
+     * @param c A {@link Capabilities} containing the new Capabilities status.
+     *
+     * @hide
+     */
+    protected final void notifyCapabilitiesStatusChanged(Capabilities c) {
+        synchronized (mLock) {
+            mCapabilityStatus = c.copy();
+        }
+        int count = mCapabilityCallbacks.beginBroadcast();
+        try {
+            for (int i = 0; i < count; i++) {
+                try {
+                    mCapabilityCallbacks.getBroadcastItem(i).onCapabilitiesStatusChanged(
+                            c.mCapabilities);
+                } catch (RemoteException e) {
+                    Log.w(LOG_TAG, e + " " + "notifyCapabilitiesStatusChanged() - Skipping " +
+                            "callback.");
+                }
+            }
+        } finally {
+            mCapabilityCallbacks.finishBroadcast();
+        }
+    }
+
+    /**
+     * Features should override this method to receive Capability preference change requests from
+     * the framework using the provided {@link CapabilityChangeRequest}. If any of the capabilities
+     * in the {@link CapabilityChangeRequest} are not able to be completed due to an error,
+     * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError} should be called for
+     * each failed capability.
+     *
+     * @param request A {@link CapabilityChangeRequest} containing requested capabilities to
+     *     enable/disable.
+     * @param c A {@link CapabilityCallbackProxy}, which will be used to call back to the framework
+     * setting a subset of these capabilities fail, using
+     * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError}.
+     */
+    public abstract void changeEnabledCapabilities(CapabilityChangeRequest request,
+            CapabilityCallbackProxy c);
+
+    /**
+     * Called when the framework is removing this feature and it needs to be cleaned up.
      */
     public abstract void onFeatureRemoved();
 
     /**
-     * @return Binder instance
+     * Called when the feature has been initialized and communication with the framework is set up.
+     * Any attempt by this feature to access the framework before this method is called will return
+     * with an {@link IllegalStateException}.
+     * The IMS provider should use this method to trigger registration for this feature on the IMS
+     * network, if needed.
      */
-    public abstract IInterface getBinder();
+    public abstract void onFeatureReady();
+
+    /**
+     * @return Binder instance that the framework will use to communicate with this feature.
+     * @hide
+     */
+    protected abstract IInterface getBinder();
 }
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
new file mode 100644
index 0000000..09267fc
--- /dev/null
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -0,0 +1,672 @@
+/*
+ * 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.feature;
+
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telecom.TelecomManager;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.telephony.ims.stub.ImsCallSessionImplBase;
+import android.telephony.ims.stub.ImsSmsImplBase;
+import android.telephony.ims.aidl.IImsCapabilityCallback;
+import android.telephony.ims.aidl.IImsMmTelFeature;
+import android.telephony.ims.aidl.IImsMmTelListener;
+import android.telephony.ims.aidl.IImsSmsListener;
+import android.telephony.ims.stub.ImsEcbmImplBase;
+import android.telephony.ims.stub.ImsMultiEndpointImplBase;
+import android.telephony.ims.stub.ImsUtImplBase;
+import android.util.Log;
+
+import android.telephony.ims.ImsCallProfile;
+import com.android.ims.internal.IImsCallSession;
+import com.android.ims.internal.IImsEcbm;
+import com.android.ims.internal.IImsMultiEndpoint;
+import com.android.ims.internal.IImsUt;
+import android.telephony.ims.ImsCallSession;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Base implementation for Voice and SMS (IR-92) and Video (IR-94) IMS support.
+ *
+ * Any class wishing to use MmTelFeature should extend this class and implement all methods that the
+ * service supports.
+ * @hide
+ */
+@SystemApi
+public class MmTelFeature extends ImsFeature {
+
+    private static final String LOG_TAG = "MmTelFeature";
+
+    private final IImsMmTelFeature mImsMMTelBinder = new IImsMmTelFeature.Stub() {
+
+        @Override
+        public void setListener(IImsMmTelListener l) throws RemoteException {
+            synchronized (mLock) {
+                MmTelFeature.this.setListener(l);
+            }
+        }
+
+        @Override
+        public int getFeatureState() throws RemoteException {
+            synchronized (mLock) {
+                try {
+                    return MmTelFeature.this.getFeatureState();
+                } catch (Exception e) {
+                    throw new RemoteException(e.getMessage());
+                }
+            }
+        }
+
+
+        @Override
+        public ImsCallProfile createCallProfile(int callSessionType, int callType)
+                throws RemoteException {
+            synchronized (mLock) {
+                try {
+                    return MmTelFeature.this.createCallProfile(callSessionType, callType);
+                } catch (Exception e) {
+                    throw new RemoteException(e.getMessage());
+                }
+            }
+        }
+
+        @Override
+        public IImsCallSession createCallSession(ImsCallProfile profile) throws RemoteException {
+            synchronized (mLock) {
+                return createCallSessionInterface(profile);
+            }
+        }
+
+        @Override
+        public int shouldProcessCall(String[] numbers) {
+            synchronized (mLock) {
+                return MmTelFeature.this.shouldProcessCall(numbers);
+            }
+        }
+
+        @Override
+        public IImsUt getUtInterface() throws RemoteException {
+            synchronized (mLock) {
+                return MmTelFeature.this.getUtInterface();
+            }
+        }
+
+        @Override
+        public IImsEcbm getEcbmInterface() throws RemoteException {
+            synchronized (mLock) {
+                return MmTelFeature.this.getEcbmInterface();
+            }
+        }
+
+        @Override
+        public void setUiTtyMode(int uiTtyMode, Message onCompleteMessage) throws RemoteException {
+            synchronized (mLock) {
+                try {
+                    MmTelFeature.this.setUiTtyMode(uiTtyMode, onCompleteMessage);
+                } catch (Exception e) {
+                    throw new RemoteException(e.getMessage());
+                }
+            }
+        }
+
+        @Override
+        public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
+            synchronized (mLock) {
+                return MmTelFeature.this.getMultiEndpointInterface();
+            }
+        }
+
+        @Override
+        public int queryCapabilityStatus() throws RemoteException {
+            return MmTelFeature.this.queryCapabilityStatus().mCapabilities;
+        }
+
+        @Override
+        public void addCapabilityCallback(IImsCapabilityCallback c) {
+            MmTelFeature.this.addCapabilityCallback(c);
+        }
+
+        @Override
+        public void removeCapabilityCallback(IImsCapabilityCallback c) {
+            MmTelFeature.this.removeCapabilityCallback(c);
+        }
+
+        @Override
+        public void changeCapabilitiesConfiguration(CapabilityChangeRequest request,
+                IImsCapabilityCallback c) throws RemoteException {
+            MmTelFeature.this.requestChangeEnabledCapabilities(request, c);
+        }
+
+        @Override
+        public void queryCapabilityConfiguration(int capability, int radioTech,
+                IImsCapabilityCallback c) {
+            queryCapabilityConfigurationInternal(capability, radioTech, c);
+        }
+
+        @Override
+        public void setSmsListener(IImsSmsListener l) throws RemoteException {
+            MmTelFeature.this.setSmsListener(l);
+        }
+
+        @Override
+        public void sendSms(int token, int messageRef, String format, String smsc, boolean retry,
+                byte[] pdu) {
+            synchronized (mLock) {
+                MmTelFeature.this.sendSms(token, messageRef, format, smsc, retry, pdu);
+            }
+        }
+
+        @Override
+        public void acknowledgeSms(int token, int messageRef, int result) {
+            synchronized (mLock) {
+                MmTelFeature.this.acknowledgeSms(token, messageRef, result);
+            }
+        }
+
+        @Override
+        public void acknowledgeSmsReport(int token, int messageRef, int result) {
+            synchronized (mLock) {
+                MmTelFeature.this.acknowledgeSmsReport(token, messageRef, result);
+            }
+        }
+
+        @Override
+        public String getSmsFormat() {
+            synchronized (mLock) {
+                return MmTelFeature.this.getSmsFormat();
+            }
+        }
+
+        @Override
+        public void onSmsReady() {
+            synchronized (mLock) {
+                MmTelFeature.this.onSmsReady();
+            }
+        }
+    };
+
+    /**
+     * Contains the capabilities defined and supported by a MmTelFeature in the form of a Bitmask.
+     * The capabilities that are used in MmTelFeature are defined as
+     * {@link MmTelCapabilities#CAPABILITY_TYPE_VOICE},
+     * {@link MmTelCapabilities#CAPABILITY_TYPE_VIDEO},
+     * {@link MmTelCapabilities#CAPABILITY_TYPE_UT}, and
+     * {@link MmTelCapabilities#CAPABILITY_TYPE_SMS}.
+     *
+     * The capabilities of this MmTelFeature will be set by the framework and can be queried with
+     * {@link #queryCapabilityStatus()}.
+     *
+     * This MmTelFeature can then return the status of each of these capabilities (enabled or not)
+     * by sending a {@link #notifyCapabilitiesStatusChanged} callback to the framework. The current
+     * status can also be queried using {@link #queryCapabilityStatus()}.
+     */
+    public static class MmTelCapabilities extends Capabilities {
+
+        /**
+         * @hide
+         */
+        @VisibleForTesting
+        public MmTelCapabilities() {
+            super();
+        }
+
+        public MmTelCapabilities(Capabilities c) {
+            mCapabilities = c.mCapabilities;
+        }
+
+        public MmTelCapabilities(int capabilities) {
+            mCapabilities = capabilities;
+        }
+
+        @IntDef(flag = true,
+                value = {
+                        CAPABILITY_TYPE_VOICE,
+                        CAPABILITY_TYPE_VIDEO,
+                        CAPABILITY_TYPE_UT,
+                        CAPABILITY_TYPE_SMS
+                })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface MmTelCapability {}
+
+        /**
+         * This MmTelFeature supports Voice calling (IR.92)
+         */
+        public static final int CAPABILITY_TYPE_VOICE = 1 << 0;
+
+        /**
+         * This MmTelFeature supports Video (IR.94)
+         */
+        public static final int CAPABILITY_TYPE_VIDEO = 1 << 1;
+
+        /**
+         * This MmTelFeature supports XCAP over Ut for supplementary services. (IR.92)
+         */
+        public static final int CAPABILITY_TYPE_UT = 1 << 2;
+
+        /**
+         * This MmTelFeature supports SMS (IR.92)
+         */
+        public static final int CAPABILITY_TYPE_SMS = 1 << 3;
+
+        @Override
+        public final void addCapabilities(@MmTelCapability int capabilities) {
+            super.addCapabilities(capabilities);
+        }
+
+        @Override
+        public final void removeCapabilities(@MmTelCapability int capability) {
+            super.removeCapabilities(capability);
+        }
+
+        @Override
+        public final boolean isCapable(@MmTelCapability int capabilities) {
+            return super.isCapable(capabilities);
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder("MmTel Capabilities - [");
+            builder.append("Voice: ");
+            builder.append(isCapable(CAPABILITY_TYPE_VOICE));
+            builder.append(" Video: ");
+            builder.append(isCapable(CAPABILITY_TYPE_VIDEO));
+            builder.append(" UT: ");
+            builder.append(isCapable(CAPABILITY_TYPE_UT));
+            builder.append(" SMS: ");
+            builder.append(isCapable(CAPABILITY_TYPE_SMS));
+            builder.append("]");
+            return builder.toString();
+        }
+    }
+
+    /**
+     * Listener that the framework implements for communication from the MmTelFeature.
+     * @hide
+     */
+    public static class Listener extends IImsMmTelListener.Stub {
+
+        /**
+         * Called when the IMS provider receives an incoming call.
+         * @param c The {@link ImsCallSession} associated with the new call.
+         */
+        @Override
+        public void onIncomingCall(IImsCallSession c, Bundle extras) {
+
+        }
+
+        /**
+         * Updates the Listener when the voice message count for IMS has changed.
+         * @param count an integer representing the new message count.
+         */
+        @Override
+        public void onVoiceMessageCountUpdate(int count) {
+
+        }
+    }
+
+    /**
+     * To be returned by {@link #shouldProcessCall(String[])} when the ImsService should process the
+     * outgoing call as IMS.
+     */
+    public static final int PROCESS_CALL_IMS = 0;
+    /**
+     * To be returned by {@link #shouldProcessCall(String[])} when the telephony framework should
+     * not process the outgoing NON_EMERGENCY call as IMS and should instead use circuit switch.
+     */
+    public static final int PROCESS_CALL_CSFB = 1;
+    /**
+     * To be returned by {@link #shouldProcessCall(String[])} when the telephony framework should
+     * not process the outgoing EMERGENCY call as IMS and should instead use circuit switch.
+     */
+    public static final int PROCESS_CALL_EMERGENCY_CSFB = 2;
+
+    @IntDef(flag = true,
+            value = {
+                    PROCESS_CALL_IMS,
+                    PROCESS_CALL_CSFB,
+                    PROCESS_CALL_EMERGENCY_CSFB
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ProcessCallResult {}
+
+
+    // Lock for feature synchronization
+    private final Object mLock = new Object();
+    private IImsMmTelListener mListener;
+
+    /**
+     * @param listener A {@link Listener} used when the MmTelFeature receives an incoming call and
+     *     notifies the framework.
+     */
+    private void setListener(IImsMmTelListener listener) {
+        synchronized (mLock) {
+            mListener = listener;
+        }
+        if (mListener != null) {
+            onFeatureReady();
+        }
+    }
+
+    private void queryCapabilityConfigurationInternal(int capability, int radioTech,
+            IImsCapabilityCallback c) {
+        boolean enabled = queryCapabilityConfiguration(capability, radioTech);
+        try {
+            if (c != null) {
+                c.onQueryCapabilityConfiguration(capability, radioTech, enabled);
+            }
+        } catch (RemoteException e) {
+            Log.e(LOG_TAG, "queryCapabilityConfigurationInternal called on dead binder!");
+        }
+    }
+
+    /**
+     * The current capability status that this MmTelFeature has defined is available. This
+     * configuration will be used by the platform to figure out which capabilities are CURRENTLY
+     * available to be used.
+     *
+     * Should be a subset of the capabilities that are enabled by the framework in
+     * {@link #changeEnabledCapabilities}.
+     * @return A copy of the current MmTelFeature capability status.
+     */
+    @Override
+    public final MmTelCapabilities queryCapabilityStatus() {
+        return new MmTelCapabilities(super.queryCapabilityStatus());
+    }
+
+    /**
+     * Notify the framework that the status of the Capabilities has changed. Even though the
+     * MmTelFeature capability may be enabled by the framework, the status may be disabled due to
+     * the feature being unavailable from the network.
+     * @param c The current capability status of the MmTelFeature. If a capability is disabled, then
+     * the status of that capability is disabled. This can happen if the network does not currently
+     * support the capability that is enabled. A capability that is disabled by the framework (via
+     * {@link #changeEnabledCapabilities}) should also show the status as disabled.
+     */
+    public final void notifyCapabilitiesStatusChanged(MmTelCapabilities c) {
+        super.notifyCapabilitiesStatusChanged(c);
+    }
+
+    /**
+     * Notify the framework of an incoming call.
+     * @param c The {@link ImsCallSessionImplBase} of the new incoming call.
+     */
+    public final void notifyIncomingCall(ImsCallSessionImplBase c, Bundle extras) {
+        synchronized (mLock) {
+            if (mListener == null) {
+                throw new IllegalStateException("Session is not available.");
+            }
+            try {
+                mListener.onIncomingCall(c.getServiceImpl(), extras);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    /**
+     *
+     * @hide
+     */
+    public final void notifyIncomingCallSession(IImsCallSession c, Bundle extras) {
+        synchronized (mLock) {
+            if (mListener == null) {
+                throw new IllegalStateException("Session is not available.");
+            }
+            try {
+                mListener.onIncomingCall(c, extras);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    /**
+     * Notify the framework of a change in the Voice Message count.
+     * @link count the new Voice Message count.
+     */
+    public final void notifyVoiceMessageCountUpdate(int count) {
+        synchronized (mLock) {
+            if (mListener == null) {
+                throw new IllegalStateException("Session is not available.");
+            }
+            try {
+                mListener.onVoiceMessageCountUpdate(count);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    /**
+     * Provides the MmTelFeature with the ability to return the framework Capability Configuration
+     * for a provided Capability. If the framework calls {@link #changeEnabledCapabilities} and
+     * includes a capability A to enable or disable, this method should return the correct enabled
+     * status for capability A.
+     * @param capability The capability that we are querying the configuration for.
+     * @return true if the capability is enabled, false otherwise.
+     */
+    public boolean queryCapabilityConfiguration(@MmTelCapabilities.MmTelCapability int capability,
+            @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
+        // Base implementation - Override to provide functionality
+        return false;
+    }
+
+    /**
+     * The MmTelFeature should override this method to handle the enabling/disabling of
+     * MmTel Features, defined in {@link MmTelCapabilities.MmTelCapability}. The framework assumes
+     * the {@link CapabilityChangeRequest} was processed successfully. If a subset of capabilities
+     * could not be set to their new values,
+     * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError} must be called
+     * individually for each capability whose processing resulted in an error.
+     *
+     * Enabling/Disabling a capability here indicates that the capability should be registered or
+     * deregistered (depending on the capability change) and become available or unavailable to
+     * the framework.
+     */
+    @Override
+    public void changeEnabledCapabilities(CapabilityChangeRequest request,
+            CapabilityCallbackProxy c) {
+        // Base implementation, no-op
+    }
+
+    /**
+     * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
+     *
+     * @param callSessionType a service type that is specified in {@link ImsCallProfile}
+     *        {@link ImsCallProfile#SERVICE_TYPE_NONE}
+     *        {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
+     *        {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
+     * @param callType a call type that is specified in {@link ImsCallProfile}
+     *        {@link ImsCallProfile#CALL_TYPE_VOICE}
+     *        {@link ImsCallProfile#CALL_TYPE_VT}
+     *        {@link ImsCallProfile#CALL_TYPE_VT_TX}
+     *        {@link ImsCallProfile#CALL_TYPE_VT_RX}
+     *        {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
+     *        {@link ImsCallProfile#CALL_TYPE_VS}
+     *        {@link ImsCallProfile#CALL_TYPE_VS_TX}
+     *        {@link ImsCallProfile#CALL_TYPE_VS_RX}
+     * @return a {@link ImsCallProfile} object
+     */
+    public ImsCallProfile createCallProfile(int callSessionType, int callType) {
+        // Base Implementation - Should be overridden
+        return null;
+    }
+
+    /**
+     * @hide
+     */
+    public IImsCallSession createCallSessionInterface(ImsCallProfile profile)
+            throws RemoteException {
+        ImsCallSessionImplBase s = MmTelFeature.this.createCallSession(profile);
+        return s != null ? s.getServiceImpl() : null;
+    }
+
+    /**
+     * Creates an {@link ImsCallSession} with the specified call profile.
+     * Use other methods, if applicable, instead of interacting with
+     * {@link ImsCallSession} directly.
+     *
+     * @param profile a call profile to make the call
+     */
+    public ImsCallSessionImplBase createCallSession(ImsCallProfile profile) {
+        // Base Implementation - Should be overridden
+        return null;
+    }
+
+    /**
+     * Called by the framework to determine if the outgoing call, designated by the outgoing
+     * {@link Uri}s, should be processed as an IMS call or CSFB call.
+     * @param numbers An array of {@link String}s that will be used for placing the call. There can
+     *         be multiple {@link String}s listed in the case when we want to place an outgoing
+     *         call as a conference.
+     * @return a {@link ProcessCallResult} to the framework, which will be used to determine if the
+     *        call wil lbe placed over IMS or via CSFB.
+     */
+    public @ProcessCallResult int shouldProcessCall(String[] numbers) {
+        return PROCESS_CALL_IMS;
+    }
+
+    /**
+     *
+     * @hide
+     */
+    protected IImsUt getUtInterface() throws RemoteException {
+        ImsUtImplBase utImpl = getUt();
+        return utImpl != null ? utImpl.getInterface() : null;
+    }
+
+    /**
+     * @hide
+     */
+    protected IImsEcbm getEcbmInterface() throws RemoteException {
+        ImsEcbmImplBase ecbmImpl = getEcbm();
+        return ecbmImpl != null ? ecbmImpl.getImsEcbm() : null;
+    }
+
+    /**
+     * @hide
+     */
+    public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
+        ImsMultiEndpointImplBase multiendpointImpl = getMultiEndpoint();
+        return multiendpointImpl != null ? multiendpointImpl.getIImsMultiEndpoint() : null;
+    }
+
+    /**
+     * @return The {@link ImsUtImplBase} Ut interface implementation for the supplementary service
+     * configuration.
+     */
+    public ImsUtImplBase getUt() {
+        // Base Implementation - Should be overridden
+        return null;
+    }
+
+    /**
+     * @return The {@link ImsEcbmImplBase} Emergency call-back mode interface for emergency VoLTE
+     * calls that support it.
+     */
+    public ImsEcbmImplBase getEcbm() {
+        // Base Implementation - Should be overridden
+        return null;
+    }
+
+    /**
+     * @return The {@link ImsMultiEndpointImplBase} implementation for implementing Dialog event
+     * package processing for multi-endpoint.
+     */
+    public ImsMultiEndpointImplBase getMultiEndpoint() {
+        // Base Implementation - Should be overridden
+        return null;
+    }
+
+    /**
+     * Sets the current UI TTY mode for the MmTelFeature.
+     * @param mode An integer containing the new UI TTY Mode, can consist of
+     *         {@link TelecomManager#TTY_MODE_OFF},
+     *         {@link TelecomManager#TTY_MODE_FULL},
+     *         {@link TelecomManager#TTY_MODE_HCO},
+     *         {@link TelecomManager#TTY_MODE_VCO}
+     * @param onCompleteMessage A {@link Message} to be used when the mode has been set.
+     */
+    public void setUiTtyMode(int mode, Message onCompleteMessage) {
+        // Base Implementation - Should be overridden
+    }
+
+    private void setSmsListener(IImsSmsListener listener) {
+        getSmsImplementation().registerSmsListener(listener);
+    }
+
+    private void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
+            byte[] pdu) {
+        getSmsImplementation().sendSms(token, messageRef, format, smsc, isRetry, pdu);
+    }
+
+    private void acknowledgeSms(int token, int messageRef,
+            @ImsSmsImplBase.DeliverStatusResult int result) {
+        getSmsImplementation().acknowledgeSms(token, messageRef, result);
+    }
+
+    private void acknowledgeSmsReport(int token, int messageRef,
+            @ImsSmsImplBase.StatusReportResult int result) {
+        getSmsImplementation().acknowledgeSmsReport(token, messageRef, result);
+    }
+
+    private void onSmsReady() {
+        getSmsImplementation().onReady();
+    }
+
+    /**
+     * Must be overridden by IMS Provider to be able to support SMS over IMS. Otherwise a default
+     * non-functional implementation is returned.
+     *
+     * @return an instance of {@link ImsSmsImplBase} which should be implemented by the IMS
+     * Provider.
+     */
+    public ImsSmsImplBase getSmsImplementation() {
+        return new ImsSmsImplBase();
+    }
+
+    private String getSmsFormat() {
+        return getSmsImplementation().getSmsFormat();
+    }
+
+    /**{@inheritDoc}*/
+    @Override
+    public void onFeatureRemoved() {
+        // Base Implementation - Should be overridden
+    }
+
+    /**{@inheritDoc}*/
+    @Override
+    public void onFeatureReady() {
+        // Base Implementation - Should be overridden
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public final IImsMmTelFeature getBinder() {
+        return mImsMMTelBinder;
+    }
+}
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index 40c5181..a637e16 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -16,16 +16,18 @@
 
 package android.telephony.ims.feature;
 
-import com.android.ims.internal.IImsRcsFeature;
+import android.annotation.SystemApi;
+import android.telephony.ims.aidl.IImsRcsFeature;
 
 /**
  * Base implementation of the RcsFeature APIs. Any ImsService wishing to support RCS should extend
  * this class and provide implementations of the RcsFeature methods that they support.
  * @hide
  */
-
+@SystemApi
 public class RcsFeature extends ImsFeature {
 
+    /**{@inheritDoc}*/
     private final IImsRcsFeature mImsRcsBinder = new IImsRcsFeature.Stub() {
         // Empty Default Implementation.
     };
@@ -35,16 +37,30 @@
         super();
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
-    public void onFeatureReady() {
-
+    public void changeEnabledCapabilities(CapabilityChangeRequest request,
+            CapabilityCallbackProxy c) {
+        // Do nothing for base implementation.
     }
 
+    /**{@inheritDoc}*/
     @Override
     public void onFeatureRemoved() {
 
     }
 
+    /**{@inheritDoc}*/
+    @Override
+    public void onFeatureReady() {
+
+    }
+
+    /**
+     * @hide
+     */
     @Override
     public final IImsRcsFeature getBinder() {
         return mImsRcsBinder;
diff --git a/telephony/java/android/telephony/ims/internal/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/internal/ImsCallSessionListener.java
deleted file mode 100644
index 5d16dd5..0000000
--- a/telephony/java/android/telephony/ims/internal/ImsCallSessionListener.java
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (C) 2017 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.internal;
-
-import android.os.RemoteException;
-import android.telephony.ims.internal.aidl.IImsCallSessionListener;
-
-import com.android.ims.ImsCallProfile;
-import com.android.ims.ImsConferenceState;
-import com.android.ims.ImsReasonInfo;
-import com.android.ims.ImsStreamMediaProfile;
-import com.android.ims.ImsSuppServiceNotification;
-import com.android.ims.internal.ImsCallSession;
-
-/**
- * Proxy class for interfacing with the framework's Call session for an ongoing IMS call.
- *
- * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
- * will break other implementations of ImsCallSessionListener maintained by other ImsServices.
- *
- * @hide
- */
-public class ImsCallSessionListener {
-
-    private final IImsCallSessionListener mListener;
-
-    public ImsCallSessionListener(IImsCallSessionListener l) {
-        mListener = l;
-    }
-
-    /**
-     * Called when a request is sent out to initiate a new session
-     * and 1xx response is received from the network.
-     */
-    public void callSessionProgressing(ImsStreamMediaProfile profile)
-            throws RemoteException {
-        mListener.callSessionProgressing(profile);
-    }
-
-    /**
-     * Called when the session is initiated.
-     *
-     * @param profile the associated {@link ImsCallSession}.
-     */
-    public void callSessionInitiated(ImsCallProfile profile) throws RemoteException {
-        mListener.callSessionInitiated(profile);
-    }
-
-    /**
-     * Called when the session establishment has failed.
-     *
-     * @param reasonInfo detailed reason of the session establishment failure
-     */
-    public void callSessionInitiatedFailed(ImsReasonInfo reasonInfo) throws RemoteException {
-        mListener.callSessionInitiatedFailed(reasonInfo);
-    }
-
-    /**
-     * Called when the session is terminated.
-     *
-     * @param reasonInfo detailed reason of the session termination
-     */
-    public void callSessionTerminated(ImsReasonInfo reasonInfo) throws RemoteException {
-        mListener.callSessionTerminated(reasonInfo);
-    }
-
-    /**
-     * Called when the session is on hold.
-     */
-    public void callSessionHeld(ImsCallProfile profile) throws RemoteException {
-        mListener.callSessionHeld(profile);
-    }
-
-    /**
-     * Called when the session hold has failed.
-     *
-     * @param reasonInfo detailed reason of the session hold failure
-     */
-    public void callSessionHoldFailed(ImsReasonInfo reasonInfo) throws RemoteException {
-        mListener.callSessionHoldFailed(reasonInfo);
-    }
-
-    /**
-     * Called when the session hold is received from the remote user.
-     */
-    public void callSessionHoldReceived(ImsCallProfile profile) throws RemoteException {
-        mListener.callSessionHoldReceived(profile);
-    }
-
-    /**
-     * Called when the session resume is done.
-     */
-    public void callSessionResumed(ImsCallProfile profile) throws RemoteException {
-        mListener.callSessionResumed(profile);
-    }
-
-    /**
-     * Called when the session resume has failed.
-     *
-     * @param reasonInfo detailed reason of the session resume failure
-     */
-    public void callSessionResumeFailed(ImsReasonInfo reasonInfo) throws RemoteException {
-        mListener.callSessionResumeFailed(reasonInfo);
-    }
-
-    /**
-     * Called when the session resume is received from the remote user.
-     */
-    public void callSessionResumeReceived(ImsCallProfile profile) throws RemoteException {
-        mListener.callSessionResumeReceived(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 newSession the session object that is merged with an active & hold session
-     */
-    public void callSessionMergeStarted(ImsCallSession newSession, ImsCallProfile profile)
-            throws RemoteException {
-        mListener.callSessionMergeStarted(newSession != null ? newSession.getSession() : null,
-                profile);
-    }
-
-    /**
-     * Called when the session merge is successful and the merged session is active.
-     *
-     * @param newSession the new session object that is used for the conference
-     */
-    public void callSessionMergeComplete(ImsCallSession newSession) throws RemoteException {
-        mListener.callSessionMergeComplete(newSession != null ? newSession.getSession() : null);
-    }
-
-    /**
-     * Called when the session merge has failed.
-     *
-     * @param reasonInfo detailed reason of the call merge failure
-     */
-    public void callSessionMergeFailed(ImsReasonInfo reasonInfo) throws RemoteException {
-        mListener.callSessionMergeFailed(reasonInfo);
-    }
-
-    /**
-     * Called when the session is updated (except for hold/unhold).
-     */
-    public void callSessionUpdated(ImsCallProfile profile) throws RemoteException {
-        mListener.callSessionUpdated(profile);
-    }
-
-    /**
-     * Called when the session update has failed.
-     *
-     * @param reasonInfo detailed reason of the session update failure
-     */
-    public void callSessionUpdateFailed(ImsReasonInfo reasonInfo) throws RemoteException {
-        mListener.callSessionUpdateFailed(reasonInfo);
-    }
-
-    /**
-     * Called when the session update is received from the remote user.
-     */
-    public void callSessionUpdateReceived(ImsCallProfile profile) throws RemoteException {
-        mListener.callSessionUpdateReceived(profile);
-    }
-
-    /**
-     * Called when the session has been extended to a conference session.
-     *
-     * @param newSession the session object that is extended to the conference
-     *      from the active session
-     */
-    public void callSessionConferenceExtended(ImsCallSession newSession, ImsCallProfile profile)
-            throws RemoteException {
-        mListener.callSessionConferenceExtended(newSession != null ? newSession.getSession() : null,
-                profile);
-    }
-
-    /**
-     * Called when the conference extension has failed.
-     *
-     * @param reasonInfo detailed reason of the conference extension failure
-     */
-    public void callSessionConferenceExtendFailed(ImsReasonInfo reasonInfo) throws RemoteException {
-        mListener.callSessionConferenceExtendFailed(reasonInfo);
-    }
-
-    /**
-     * Called when the conference extension is received from the remote user.
-     */
-    public void callSessionConferenceExtendReceived(ImsCallSession newSession,
-            ImsCallProfile profile) throws RemoteException {
-        mListener.callSessionConferenceExtendReceived(newSession != null
-                ? newSession.getSession() : null, profile);
-    }
-
-    /**
-     * Called when the invitation request of the participants is delivered to the conference
-     * server.
-     */
-    public void callSessionInviteParticipantsRequestDelivered() throws RemoteException {
-        mListener.callSessionInviteParticipantsRequestDelivered();
-    }
-
-    /**
-     * Called when the invitation request of the participants has failed.
-     *
-     * @param reasonInfo detailed reason of the conference invitation failure
-     */
-    public void callSessionInviteParticipantsRequestFailed(ImsReasonInfo reasonInfo)
-            throws RemoteException {
-        mListener.callSessionInviteParticipantsRequestFailed(reasonInfo);
-    }
-
-    /**
-     * Called when the removal request of the participants is delivered to the conference
-     * server.
-     */
-    public void callSessionRemoveParticipantsRequestDelivered() throws RemoteException {
-        mListener.callSessionRemoveParticipantsRequestDelivered();
-    }
-
-    /**
-     * Called when the removal request of the participants has failed.
-     *
-     * @param reasonInfo detailed reason of the conference removal failure
-     */
-    public void callSessionRemoveParticipantsRequestFailed(ImsReasonInfo reasonInfo)
-            throws RemoteException {
-        mListener.callSessionInviteParticipantsRequestFailed(reasonInfo);
-    }
-
-    /**
-     * Notifies the framework of the updated Call session conference state.
-     *
-     * @param state the new {@link ImsConferenceState} associated with the conference.
-     */
-    public void callSessionConferenceStateUpdated(ImsConferenceState state) throws RemoteException {
-        mListener.callSessionConferenceStateUpdated(state);
-    }
-
-    /**
-     * Notifies the incoming USSD message.
-     */
-    public void callSessionUssdMessageReceived(int mode, String ussdMessage)
-            throws RemoteException {
-        mListener.callSessionUssdMessageReceived(mode, ussdMessage);
-    }
-
-    /**
-     * Notifies of a case where a {@link com.android.ims.internal.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}.
-     */
-    public void callSessionMayHandover(int srcAccessTech, int targetAccessTech)
-            throws RemoteException {
-        mListener.callSessionMayHandover(srcAccessTech, targetAccessTech);
-    }
-
-    /**
-     * Called when session access technology changes.
-     *
-     * @param srcAccessTech original access technology
-     * @param targetAccessTech new access technology
-     * @param reasonInfo
-     */
-    public void callSessionHandover(int srcAccessTech, int targetAccessTech,
-            ImsReasonInfo reasonInfo) throws RemoteException {
-        mListener.callSessionHandover(srcAccessTech, targetAccessTech, reasonInfo);
-    }
-
-    /**
-     * Called when session access technology change fails.
-     *
-     * @param srcAccessTech original access technology
-     * @param targetAccessTech new access technology
-     * @param reasonInfo handover failure reason
-     */
-    public void callSessionHandoverFailed(int srcAccessTech, int targetAccessTech,
-            ImsReasonInfo reasonInfo) throws RemoteException {
-        mListener.callSessionHandoverFailed(srcAccessTech, targetAccessTech, reasonInfo);
-    }
-
-    /**
-     * Called when the TTY mode is changed by the remote party.
-     *
-     * @param mode one of the following: -
-     *             {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} -
-     *             {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} -
-     *             {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} -
-     *             {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
-     */
-    public void callSessionTtyModeReceived(int mode) throws RemoteException {
-        mListener.callSessionTtyModeReceived(mode);
-    }
-
-    /**
-     * Called when the multiparty state is changed for this {@code ImsCallSession}.
-     *
-     * @param isMultiParty {@code true} if the session became multiparty,
-     *                     {@code false} otherwise.
-     */
-
-    public void callSessionMultipartyStateChanged(boolean isMultiParty) throws RemoteException {
-        mListener.callSessionMultipartyStateChanged(isMultiParty);
-    }
-
-    /**
-     * Called when the supplementary service information is received for the current session.
-     */
-    public void callSessionSuppServiceReceived(ImsSuppServiceNotification suppSrvNotification)
-            throws RemoteException {
-        mListener.callSessionSuppServiceReceived(suppSrvNotification);
-    }
-
-    /**
-     * Received RTT modify request from the remote party.
-     *
-     * @param callProfile ImsCallProfile with updated attributes
-     */
-    public void callSessionRttModifyRequestReceived(ImsCallProfile callProfile)
-            throws RemoteException {
-        mListener.callSessionRttModifyRequestReceived(callProfile);
-    }
-
-    /**
-     * @param status the received response for RTT modify request.
-     */
-    public void callSessionRttModifyResponseReceived(int status) throws RemoteException {
-        mListener.callSessionRttModifyResponseReceived(status);
-    }
-
-    /**
-     * Device received RTT message from Remote UE.
-     *
-     * @param rttMessage RTT message received
-     */
-    public void callSessionRttMessageReceived(String rttMessage) throws RemoteException {
-        mListener.callSessionRttMessageReceived(rttMessage);
-    }
-}
-
diff --git a/telephony/java/android/telephony/ims/internal/ImsService.java b/telephony/java/android/telephony/ims/internal/ImsService.java
deleted file mode 100644
index afaf332..0000000
--- a/telephony/java/android/telephony/ims/internal/ImsService.java
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Copyright (C) 2017 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.internal;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.telephony.CarrierConfigManager;
-import android.telephony.ims.internal.aidl.IImsConfig;
-import android.telephony.ims.internal.aidl.IImsMmTelFeature;
-import android.telephony.ims.internal.aidl.IImsRcsFeature;
-import android.telephony.ims.internal.aidl.IImsServiceController;
-import android.telephony.ims.internal.aidl.IImsServiceControllerListener;
-import android.telephony.ims.internal.feature.ImsFeature;
-import android.telephony.ims.internal.feature.MmTelFeature;
-import android.telephony.ims.internal.feature.RcsFeature;
-import android.telephony.ims.internal.stub.ImsConfigImplBase;
-import android.telephony.ims.internal.stub.ImsFeatureConfiguration;
-import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.ims.internal.IImsFeatureStatusCallback;
-import com.android.ims.internal.IImsRegistration;
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend
- * ImsService must register the service in their AndroidManifest to be detected by the framework.
- * First, the application must declare that they use the "android.permission.BIND_IMS_SERVICE"
- * permission. Then, the ImsService definition in the manifest must follow the following format:
- *
- * ...
- * <service android:name=".EgImsService"
- *     android:permission="android.permission.BIND_IMS_SERVICE" >
- *     <!-- Apps must declare which features they support as metadata. The different categories are
- *     defined below. In this example, the RCS_FEATURE feature is supported. -->
- *     <meta-data android:name="android.telephony.ims.RCS_FEATURE" android:value="true" />
- *     <intent-filter>
- *         <action android:name="android.telephony.ims.ImsService" />
- *     </intent-filter>
- * </service>
- * ...
- *
- * The telephony framework will then bind to the ImsService you have defined in your manifest
- * if you are either:
- * 1) Defined as the default ImsService for the device in the device overlay using
- *    "config_ims_package".
- * 2) Defined as a Carrier Provided ImsService in the Carrier Configuration using
- *    {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}.
- *
- * The features that are currently supported in an ImsService are:
- * - RCS_FEATURE: This ImsService implements the RcsFeature class.
- * - MMTEL_FEATURE: This ImsService implements the MmTelFeature class.
- *   @hide
- */
-public class ImsService extends Service {
-
-    private static final String LOG_TAG = "ImsService";
-
-    /**
-     * The intent that must be defined as an intent-filter in the AndroidManifest of the ImsService.
-     * @hide
-     */
-    public static final String SERVICE_INTERFACE = "android.telephony.ims.ImsService";
-
-    // A map of slot Id -> map of features (indexed by ImsFeature feature id) corresponding to that
-    // slot.
-    // We keep track of this to facilitate cleanup of the IImsFeatureStatusCallback and
-    // call ImsFeature#onFeatureRemoved.
-    private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>();
-
-    private IImsServiceControllerListener mListener;
-
-
-    /**
-     * Listener that notifies the framework of ImsService changes.
-     */
-    public static class Listener extends IImsServiceControllerListener.Stub {
-        /**
-         * The IMS features that this ImsService supports has changed.
-         * @param c a new {@link ImsFeatureConfiguration} containing {@link ImsFeature.FeatureType}s
-         *   that this ImsService supports. This may trigger the addition/removal of feature
-         *   in this service.
-         */
-        public void onUpdateSupportedImsFeatures(ImsFeatureConfiguration c) {
-        }
-    }
-
-    /**
-     * @hide
-     */
-    protected final IBinder mImsServiceController = new IImsServiceController.Stub() {
-        @Override
-        public void setListener(IImsServiceControllerListener l) {
-            mListener = l;
-        }
-
-        @Override
-        public IImsMmTelFeature createMmTelFeature(int slotId, IImsFeatureStatusCallback c) {
-            return createMmTelFeatureInternal(slotId, c);
-        }
-
-        @Override
-        public IImsRcsFeature createRcsFeature(int slotId, IImsFeatureStatusCallback c) {
-            return createRcsFeatureInternal(slotId, c);
-        }
-
-        @Override
-        public void removeImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c)
-                throws RemoteException {
-            ImsService.this.removeImsFeature(slotId, featureType, c);
-        }
-
-        @Override
-        public ImsFeatureConfiguration querySupportedImsFeatures() {
-            return ImsService.this.querySupportedImsFeatures();
-        }
-
-        @Override
-        public void notifyImsServiceReadyForFeatureCreation() {
-            ImsService.this.readyForFeatureCreation();
-        }
-
-        @Override
-        public void notifyImsFeatureReady(int slotId, int featureType)
-                throws RemoteException {
-            ImsService.this.notifyImsFeatureReady(slotId, featureType);
-        }
-
-        @Override
-        public IImsConfig getConfig(int slotId) throws RemoteException {
-            ImsConfigImplBase c = ImsService.this.getConfig(slotId);
-            return c != null ? c.getBinder() : null;
-        }
-
-        @Override
-        public IImsRegistration getRegistration(int slotId) throws RemoteException {
-            ImsRegistrationImplBase r = ImsService.this.getRegistration(slotId);
-            return r != null ? r.getBinder() : null;
-        }
-    };
-
-    /**
-     * @hide
-     */
-    @Override
-    public IBinder onBind(Intent intent) {
-        if(SERVICE_INTERFACE.equals(intent.getAction())) {
-            Log.i(LOG_TAG, "ImsService Bound.");
-            return mImsServiceController;
-        }
-        return null;
-    }
-
-    /**
-     * @hide
-     */
-    @VisibleForTesting
-    public SparseArray<ImsFeature> getFeatures(int slotId) {
-        return mFeaturesBySlot.get(slotId);
-    }
-
-    private IImsMmTelFeature createMmTelFeatureInternal(int slotId,
-            IImsFeatureStatusCallback c) {
-        MmTelFeature f = createMmTelFeature(slotId);
-        if (f != null) {
-            setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL, c);
-            return f.getBinder();
-        } else {
-            Log.e(LOG_TAG, "createMmTelFeatureInternal: null feature returned.");
-            return null;
-        }
-    }
-
-    private IImsRcsFeature createRcsFeatureInternal(int slotId,
-            IImsFeatureStatusCallback c) {
-        RcsFeature f = createRcsFeature(slotId);
-        if (f != null) {
-            setupFeature(f, slotId, ImsFeature.FEATURE_RCS, c);
-            return f.getBinder();
-        } else {
-            Log.e(LOG_TAG, "createRcsFeatureInternal: null feature returned.");
-            return null;
-        }
-    }
-
-    private void setupFeature(ImsFeature f, int slotId, int featureType,
-            IImsFeatureStatusCallback c) {
-        f.addImsFeatureStatusCallback(c);
-        f.initialize(this, slotId);
-        addImsFeature(slotId, featureType, f);
-    }
-
-    private void addImsFeature(int slotId, int featureType, ImsFeature f) {
-        synchronized (mFeaturesBySlot) {
-            // Get SparseArray for Features, by querying slot Id
-            SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
-            if (features == null) {
-                // Populate new SparseArray of features if it doesn't exist for this slot yet.
-                features = new SparseArray<>();
-                mFeaturesBySlot.put(slotId, features);
-            }
-            features.put(featureType, f);
-        }
-    }
-
-    private void removeImsFeature(int slotId, int featureType,
-            IImsFeatureStatusCallback c) {
-        synchronized (mFeaturesBySlot) {
-            // get ImsFeature associated with the slot/feature
-            SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
-            if (features == null) {
-                Log.w(LOG_TAG, "Can not remove ImsFeature. No ImsFeatures exist on slot "
-                        + slotId);
-                return;
-            }
-            ImsFeature f = features.get(featureType);
-            if (f == null) {
-                Log.w(LOG_TAG, "Can not remove ImsFeature. No feature with type "
-                        + featureType + " exists on slot " + slotId);
-                return;
-            }
-            f.removeImsFeatureStatusCallback(c);
-            f.onFeatureRemoved();
-            features.remove(featureType);
-        }
-    }
-
-    private void notifyImsFeatureReady(int slotId, int featureType) {
-        synchronized (mFeaturesBySlot) {
-            // get ImsFeature associated with the slot/feature
-            SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
-            if (features == null) {
-                Log.w(LOG_TAG, "Can not notify ImsFeature ready. No ImsFeatures exist on " +
-                        "slot " + slotId);
-                return;
-            }
-            ImsFeature f = features.get(featureType);
-            if (f == null) {
-                Log.w(LOG_TAG, "Can not notify ImsFeature ready. No feature with type "
-                        + featureType + " exists on slot " + slotId);
-                return;
-            }
-            f.onFeatureReady();
-        }
-    }
-
-    /**
-     * When called, provide the {@link ImsFeatureConfiguration} that this ImsService currently
-     * supports. This will trigger the framework to set up the {@link ImsFeature}s that correspond
-     * to the {@link ImsFeature.FeatureType}s configured here.
-     * @return an {@link ImsFeatureConfiguration} containing Features this ImsService supports,
-     * defined in {@link ImsFeature.FeatureType}.
-     */
-    public ImsFeatureConfiguration querySupportedImsFeatures() {
-        // Return empty for base implementation
-        return new ImsFeatureConfiguration();
-    }
-
-    /**
-     * Updates the framework with a new {@link ImsFeatureConfiguration} containing the updated
-     * features, defined in {@link ImsFeature.FeatureType} that this ImsService supports. This may
-     * trigger the framework to add/remove new ImsFeatures, depending on the configuration.
-     */
-    public final void onUpdateSupportedImsFeatures(ImsFeatureConfiguration c)
-            throws RemoteException {
-        if (mListener == null) {
-            throw new IllegalStateException("Framework is not ready");
-        }
-        mListener.onUpdateSupportedImsFeatures(c);
-    }
-
-    /**
-     * The ImsService has been bound and is ready for ImsFeature creation based on the Features that
-     * the ImsService has registered for with the framework, either in the manifest or via
-     * The ImsService should use this signal instead of onCreate/onBind or similar to perform
-     * feature initialization because the framework may bind to this service multiple times to
-     * query the ImsService's {@link ImsFeatureConfiguration} via
-     * {@link #querySupportedImsFeatures()}before creating features.
-     */
-    public void readyForFeatureCreation() {
-    }
-
-    /**
-     * When called, the framework is requesting that a new MmTelFeature is created for the specified
-     * slot.
-     *
-     * @param slotId The slot ID that the MMTel Feature is being created for.
-     * @return The newly created MmTelFeature associated with the slot or null if the feature is not
-     * supported.
-     */
-    public MmTelFeature createMmTelFeature(int slotId) {
-        return null;
-    }
-
-    /**
-     * When called, the framework is requesting that a new RcsFeature is created for the specified
-     * slot
-     *
-     * @param slotId The slot ID that the RCS Feature is being created for.
-     * @return The newly created RcsFeature associated with the slot or null if the feature is not
-     * supported.
-     */
-    public RcsFeature createRcsFeature(int slotId) {
-        return null;
-    }
-
-    /**
-     * @param slotId The slot that the IMS configuration is associated with.
-     * @return ImsConfig implementation that is associated with the specified slot.
-     */
-    public ImsConfigImplBase getConfig(int slotId) {
-        return new ImsConfigImplBase();
-    }
-
-    /**
-     * @param slotId The slot that is associated with the IMS Registration.
-     * @return the ImsRegistration implementation associated with the slot.
-     */
-    public ImsRegistrationImplBase getRegistration(int slotId) {
-        return new ImsRegistrationImplBase();
-    }
-}
diff --git a/telephony/java/android/telephony/ims/internal/feature/ImsFeature.java b/telephony/java/android/telephony/ims/internal/feature/ImsFeature.java
deleted file mode 100644
index 9f82ad2..0000000
--- a/telephony/java/android/telephony/ims/internal/feature/ImsFeature.java
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * Copyright (C) 2017 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.internal.feature;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.content.Context;
-import android.content.Intent;
-import android.os.IInterface;
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.telephony.SubscriptionManager;
-import android.telephony.ims.internal.aidl.IImsCapabilityCallback;
-import android.util.Log;
-
-import com.android.ims.internal.IImsFeatureStatusCallback;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.Set;
-import java.util.WeakHashMap;
-
-/**
- * Base class for all IMS features that are supported by the framework.
- *
- * @hide
- */
-public abstract class ImsFeature {
-
-    private static final String LOG_TAG = "ImsFeature";
-
-    /**
-     * Action to broadcast when ImsService is up.
-     * Internal use only.
-     * Only defined here separately for compatibility purposes with the old ImsService.
-     *
-     * @hide
-     */
-    public static final String ACTION_IMS_SERVICE_UP =
-            "com.android.ims.IMS_SERVICE_UP";
-
-    /**
-     * Action to broadcast when ImsService is down.
-     * Internal use only.
-     * Only defined here separately for compatibility purposes with the old ImsService.
-     *
-     * @hide
-     */
-    public static final String ACTION_IMS_SERVICE_DOWN =
-            "com.android.ims.IMS_SERVICE_DOWN";
-
-    /**
-     * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
-     * A long value; the phone ID corresponding to the IMS service coming up or down.
-     * Only defined here separately for compatibility purposes with the old ImsService.
-     *
-     * @hide
-     */
-    public static final String EXTRA_PHONE_ID = "android:phone_id";
-
-    // Invalid feature value
-    public static final int FEATURE_INVALID = -1;
-    // ImsFeatures that are defined in the Manifests. Ensure that these values match the previously
-    // defined values in ImsServiceClass for compatibility purposes.
-    public static final int FEATURE_EMERGENCY_MMTEL = 0;
-    public static final int FEATURE_MMTEL = 1;
-    public static final int FEATURE_RCS = 2;
-    // Total number of features defined
-    public static final int FEATURE_MAX = 3;
-
-    // Integer values defining IMS features that are supported in ImsFeature.
-    @IntDef(flag = true,
-            value = {
-                    FEATURE_EMERGENCY_MMTEL,
-                    FEATURE_MMTEL,
-                    FEATURE_RCS
-            })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface FeatureType {}
-
-    // Integer values defining the state of the ImsFeature at any time.
-    @IntDef(flag = true,
-            value = {
-                    STATE_UNAVAILABLE,
-                    STATE_INITIALIZING,
-                    STATE_READY,
-            })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ImsState {}
-
-    public static final int STATE_UNAVAILABLE = 0;
-    public static final int STATE_INITIALIZING = 1;
-    public static final int STATE_READY = 2;
-
-    // Integer values defining the result codes that should be returned from
-    // {@link changeEnabledCapabilities} when the framework tries to set a feature's capability.
-    @IntDef(flag = true,
-            value = {
-                    CAPABILITY_ERROR_GENERIC,
-                    CAPABILITY_SUCCESS
-            })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ImsCapabilityError {}
-
-    public static final int CAPABILITY_ERROR_GENERIC = -1;
-    public static final int CAPABILITY_SUCCESS = 0;
-
-
-    /**
-     * The framework implements this callback in order to register for Feature Capability status
-     * updates, via {@link #onCapabilitiesStatusChanged(Capabilities)}, query Capability
-     * configurations, via {@link #onQueryCapabilityConfiguration}, as well as to receive error
-     * callbacks when the ImsService can not change the capability as requested, via
-     * {@link #onChangeCapabilityConfigurationError}.
-     */
-    public static class CapabilityCallback extends IImsCapabilityCallback.Stub {
-
-        @Override
-        public final void onCapabilitiesStatusChanged(int config) throws RemoteException {
-            onCapabilitiesStatusChanged(new Capabilities(config));
-        }
-
-        /**
-         * Returns the result of a query for the capability configuration of a requested capability.
-         *
-         * @param capability The capability that was requested.
-         * @param radioTech The IMS radio technology associated with the capability.
-         * @param isEnabled true if the capability is enabled, false otherwise.
-         */
-        @Override
-        public void onQueryCapabilityConfiguration(int capability, int radioTech,
-                boolean isEnabled) {
-
-        }
-
-        /**
-         * Called when a change to the capability configuration has returned an error.
-         *
-         * @param capability The capability that was requested to be changed.
-         * @param radioTech The IMS radio technology associated with the capability.
-         * @param reason error associated with the failure to change configuration.
-         */
-        @Override
-        public void onChangeCapabilityConfigurationError(int capability, int radioTech,
-                int reason) {
-        }
-
-        /**
-         * The status of the feature's capabilities has changed to either available or unavailable.
-         * If unavailable, the feature is not able to support the unavailable capability at this
-         * time.
-         *
-         * @param config The new availability of the capabilities.
-         */
-        public void onCapabilitiesStatusChanged(Capabilities config) {
-        }
-    }
-
-    /**
-     * Used by the ImsFeature to call back to the CapabilityCallback that the framework has
-     * provided.
-     */
-    protected static class CapabilityCallbackProxy {
-        private final IImsCapabilityCallback mCallback;
-
-        public CapabilityCallbackProxy(IImsCapabilityCallback c) {
-            mCallback = c;
-        }
-
-        /**
-         * This method notifies the provided framework callback that the request to change the
-         * indicated capability has failed and has not changed.
-         *
-         * @param capability The Capability that will be notified to the framework.
-         * @param radioTech The radio tech that this capability failed for.
-         * @param reason The reason this capability was unable to be changed.
-         */
-        public void onChangeCapabilityConfigurationError(int capability, int radioTech,
-                @ImsCapabilityError int reason) {
-            try {
-                mCallback.onChangeCapabilityConfigurationError(capability, radioTech, reason);
-            } catch (RemoteException e) {
-                Log.e(LOG_TAG, "onChangeCapabilityConfigurationError called on dead binder.");
-            }
-        }
-
-        public void onQueryCapabilityConfiguration(int capability, int radioTech,
-                boolean isEnabled) {
-            try {
-                mCallback.onQueryCapabilityConfiguration(capability, radioTech, isEnabled);
-            } catch (RemoteException e) {
-                Log.e(LOG_TAG, "onQueryCapabilityConfiguration called on dead binder.");
-            }
-        }
-    }
-
-    /**
-     * Contains the capabilities defined and supported by an ImsFeature in the form of a bit mask.
-     */
-    public static class Capabilities {
-        protected int mCapabilities = 0;
-
-        public Capabilities() {
-        }
-
-        protected Capabilities(int capabilities) {
-            mCapabilities = capabilities;
-        }
-
-        /**
-         * @param capabilities Capabilities to be added to the configuration in the form of a
-         *     bit mask.
-         */
-        public void addCapabilities(int capabilities) {
-            mCapabilities |= capabilities;
-        }
-
-        /**
-         * @param capabilities Capabilities to be removed to the configuration in the form of a
-         *     bit mask.
-         */
-        public void removeCapabilities(int capabilities) {
-            mCapabilities &= ~capabilities;
-        }
-
-        /**
-         * @return true if all of the capabilities specified are capable.
-         */
-        public boolean isCapable(int capabilities) {
-            return (mCapabilities & capabilities) == capabilities;
-        }
-
-        public Capabilities copy() {
-            return new Capabilities(mCapabilities);
-        }
-
-        /**
-         * @return a bitmask containing the capability flags directly.
-         */
-        public int getMask() {
-            return mCapabilities;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (!(o instanceof Capabilities)) return false;
-
-            Capabilities that = (Capabilities) o;
-
-            return mCapabilities == that.mCapabilities;
-        }
-
-        @Override
-        public int hashCode() {
-            return mCapabilities;
-        }
-    }
-
-    private final Set<IImsFeatureStatusCallback> mStatusCallbacks = Collections.newSetFromMap(
-            new WeakHashMap<IImsFeatureStatusCallback, Boolean>());
-    private @ImsState int mState = STATE_UNAVAILABLE;
-    private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
-    private Context mContext;
-    private final Object mLock = new Object();
-    private final RemoteCallbackList<IImsCapabilityCallback> mCapabilityCallbacks
-            = new RemoteCallbackList<>();
-    private Capabilities mCapabilityStatus = new Capabilities();
-
-    public final void initialize(Context context, int slotId) {
-        mContext = context;
-        mSlotId = slotId;
-    }
-
-    public final int getFeatureState() {
-        synchronized (mLock) {
-            return mState;
-        }
-    }
-
-    protected final void setFeatureState(@ImsState int state) {
-        synchronized (mLock) {
-            if (mState != state) {
-                mState = state;
-                notifyFeatureState(state);
-            }
-        }
-    }
-
-    // Not final for testing, but shouldn't be extended!
-    @VisibleForTesting
-    public void addImsFeatureStatusCallback(@NonNull IImsFeatureStatusCallback c) {
-        try {
-            // If we have just connected, send queued status.
-            c.notifyImsFeatureStatus(getFeatureState());
-            // Add the callback if the callback completes successfully without a RemoteException.
-            synchronized (mLock) {
-                mStatusCallbacks.add(c);
-            }
-        } catch (RemoteException e) {
-            Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage());
-        }
-    }
-
-    @VisibleForTesting
-    // Not final for testing, but should not be extended!
-    public void removeImsFeatureStatusCallback(@NonNull IImsFeatureStatusCallback c) {
-        synchronized (mLock) {
-            mStatusCallbacks.remove(c);
-        }
-    }
-
-    /**
-     * Internal method called by ImsFeature when setFeatureState has changed.
-     */
-    private void notifyFeatureState(@ImsState int state) {
-        synchronized (mLock) {
-            for (Iterator<IImsFeatureStatusCallback> iter = mStatusCallbacks.iterator();
-                    iter.hasNext(); ) {
-                IImsFeatureStatusCallback callback = iter.next();
-                try {
-                    Log.i(LOG_TAG, "notifying ImsFeatureState=" + state);
-                    callback.notifyImsFeatureStatus(state);
-                } catch (RemoteException e) {
-                    // remove if the callback is no longer alive.
-                    iter.remove();
-                    Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage());
-                }
-            }
-        }
-        sendImsServiceIntent(state);
-    }
-
-    /**
-     * Provide backwards compatibility using deprecated service UP/DOWN intents.
-     */
-    private void sendImsServiceIntent(@ImsState int state) {
-        if (mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
-            return;
-        }
-        Intent intent;
-        switch (state) {
-            case ImsFeature.STATE_UNAVAILABLE:
-            case ImsFeature.STATE_INITIALIZING:
-                intent = new Intent(ACTION_IMS_SERVICE_DOWN);
-                break;
-            case ImsFeature.STATE_READY:
-                intent = new Intent(ACTION_IMS_SERVICE_UP);
-                break;
-            default:
-                intent = new Intent(ACTION_IMS_SERVICE_DOWN);
-        }
-        intent.putExtra(EXTRA_PHONE_ID, mSlotId);
-        mContext.sendBroadcast(intent);
-    }
-
-    public final void addCapabilityCallback(IImsCapabilityCallback c) {
-        mCapabilityCallbacks.register(c);
-    }
-
-    public final void removeCapabilityCallback(IImsCapabilityCallback c) {
-        mCapabilityCallbacks.unregister(c);
-    }
-
-    /**
-     * @return the cached capabilities status for this feature.
-     */
-    @VisibleForTesting
-    public Capabilities queryCapabilityStatus() {
-        synchronized (mLock) {
-            return mCapabilityStatus.copy();
-        }
-    }
-
-    // Called internally to request the change of enabled capabilities.
-    @VisibleForTesting
-    public final void requestChangeEnabledCapabilities(CapabilityChangeRequest request,
-            IImsCapabilityCallback c) throws RemoteException {
-        if (request == null) {
-            throw new IllegalArgumentException(
-                    "ImsFeature#requestChangeEnabledCapabilities called with invalid params.");
-        }
-        changeEnabledCapabilities(request, new CapabilityCallbackProxy(c));
-    }
-
-    /**
-     * Called by the ImsFeature when the capabilities status has changed.
-     *
-     * @param c A {@link Capabilities} containing the new Capabilities status.
-     */
-    protected final void notifyCapabilitiesStatusChanged(Capabilities c) {
-        synchronized (mLock) {
-            mCapabilityStatus = c.copy();
-        }
-        int count = mCapabilityCallbacks.beginBroadcast();
-        try {
-            for (int i = 0; i < count; i++) {
-                try {
-                    mCapabilityCallbacks.getBroadcastItem(i).onCapabilitiesStatusChanged(
-                            c.mCapabilities);
-                } catch (RemoteException e) {
-                    Log.w(LOG_TAG, e + " " + "notifyCapabilitiesStatusChanged() - Skipping " +
-                            "callback.");
-                }
-            }
-        } finally {
-            mCapabilityCallbacks.finishBroadcast();
-        }
-    }
-
-    /**
-     * Features should override this method to receive Capability preference change requests from
-     * the framework using the provided {@link CapabilityChangeRequest}. If any of the capabilities
-     * in the {@link CapabilityChangeRequest} are not able to be completed due to an error,
-     * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError} should be called for
-     * each failed capability.
-     *
-     * @param request A {@link CapabilityChangeRequest} containing requested capabilities to
-     *     enable/disable.
-     * @param c A {@link CapabilityCallbackProxy}, which will be used to call back to the framework
-     * setting a subset of these capabilities fail, using
-     * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError}.
-     */
-    public abstract void changeEnabledCapabilities(CapabilityChangeRequest request,
-            CapabilityCallbackProxy c);
-
-    /**
-     * Called when the framework is removing this feature and it needs to be cleaned up.
-     */
-    public abstract void onFeatureRemoved();
-
-    /**
-     * Called when the feature has been initialized and communication with the framework is set up.
-     * Any attempt by this feature to access the framework before this method is called will return
-     * with an {@link IllegalStateException}.
-     * The IMS provider should use this method to trigger registration for this feature on the IMS
-     * network, if needed.
-     */
-    public abstract void onFeatureReady();
-
-    /**
-     * @return Binder instance that the framework will use to communicate with this feature.
-     */
-    protected abstract IInterface getBinder();
-}
diff --git a/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java
deleted file mode 100644
index 9b576c7..0000000
--- a/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * Copyright (C) 2017 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.internal.feature;
-
-import android.annotation.IntDef;
-import android.os.Message;
-import android.os.RemoteException;
-import android.telecom.TelecomManager;
-import android.telephony.ims.internal.ImsCallSessionListener;
-import android.telephony.ims.internal.aidl.IImsCallSessionListener;
-import android.telephony.ims.internal.aidl.IImsCapabilityCallback;
-import android.telephony.ims.internal.aidl.IImsMmTelFeature;
-import android.telephony.ims.internal.aidl.IImsMmTelListener;
-import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.telephony.ims.stub.ImsEcbmImplBase;
-import android.telephony.ims.stub.ImsMultiEndpointImplBase;
-import android.telephony.ims.stub.ImsUtImplBase;
-import android.util.Log;
-
-import com.android.ims.ImsCallProfile;
-import com.android.ims.internal.IImsCallSession;
-import com.android.ims.internal.IImsEcbm;
-import com.android.ims.internal.IImsMultiEndpoint;
-import com.android.ims.internal.IImsUt;
-import com.android.ims.internal.ImsCallSession;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Base implementation for Voice and SMS (IR-92) and Video (IR-94) IMS support.
- *
- * Any class wishing to use MmTelFeature should extend this class and implement all methods that the
- * service supports.
- * @hide
- */
-
-public class MmTelFeature extends ImsFeature {
-
-    private static final String LOG_TAG = "MmTelFeature";
-
-    private final IImsMmTelFeature mImsMMTelBinder = new IImsMmTelFeature.Stub() {
-
-        @Override
-        public void setListener(IImsMmTelListener l) throws RemoteException {
-            synchronized (mLock) {
-                MmTelFeature.this.setListener(l);
-            }
-        }
-
-        @Override
-        public int getFeatureState() throws RemoteException {
-            synchronized (mLock) {
-                return MmTelFeature.this.getFeatureState();
-            }
-        }
-
-
-        @Override
-        public ImsCallProfile createCallProfile(int callSessionType, int callType)
-                throws RemoteException {
-            synchronized (mLock) {
-                return MmTelFeature.this.createCallProfile(callSessionType,  callType);
-            }
-        }
-
-        @Override
-        public IImsCallSession createCallSession(ImsCallProfile profile,
-                IImsCallSessionListener listener) throws RemoteException {
-            synchronized (mLock) {
-                ImsCallSession s = MmTelFeature.this.createCallSession(profile,
-                        new ImsCallSessionListener(listener));
-                return s != null ? s.getSession() : null;
-            }
-        }
-
-        @Override
-        public IImsUt getUtInterface() throws RemoteException {
-            synchronized (mLock) {
-                return MmTelFeature.this.getUt();
-            }
-        }
-
-        @Override
-        public IImsEcbm getEcbmInterface() throws RemoteException {
-            synchronized (mLock) {
-                return MmTelFeature.this.getEcbm();
-            }
-        }
-
-        @Override
-        public void setUiTtyMode(int uiTtyMode, Message onCompleteMessage) throws RemoteException {
-            synchronized (mLock) {
-                MmTelFeature.this.setUiTtyMode(uiTtyMode, onCompleteMessage);
-            }
-        }
-
-        @Override
-        public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
-            synchronized (mLock) {
-                return MmTelFeature.this.getMultiEndpoint();
-            }
-        }
-
-        @Override
-        public int queryCapabilityStatus() throws RemoteException {
-            return MmTelFeature.this.queryCapabilityStatus().mCapabilities;
-        }
-
-        @Override
-        public void addCapabilityCallback(IImsCapabilityCallback c) {
-            MmTelFeature.this.addCapabilityCallback(c);
-        }
-
-        @Override
-        public void removeCapabilityCallback(IImsCapabilityCallback c) {
-            MmTelFeature.this.removeCapabilityCallback(c);
-        }
-
-        @Override
-        public void changeCapabilitiesConfiguration(CapabilityChangeRequest request,
-                IImsCapabilityCallback c) throws RemoteException {
-            MmTelFeature.this.requestChangeEnabledCapabilities(request, c);
-        }
-
-        @Override
-        public void queryCapabilityConfiguration(int capability, int radioTech,
-                IImsCapabilityCallback c) {
-            queryCapabilityConfigurationInternal(capability, radioTech, c);
-        }
-    };
-
-    /**
-     * Contains the capabilities defined and supported by a MmTelFeature in the form of a Bitmask.
-     * The capabilities that are used in MmTelFeature are defined by {@link MmTelCapability}.
-     *
-     * The capabilities of this MmTelFeature will be set by the framework and can be queried with
-     * {@link #queryCapabilityStatus()}.
-     *
-     * This MmTelFeature can then return the status of each of these capabilities (enabled or not)
-     * by sending a {@link #notifyCapabilitiesStatusChanged} callback to the framework. The current
-     * status can also be queried using {@link #queryCapabilityStatus()}.
-     */
-    public static class MmTelCapabilities extends Capabilities {
-
-        @VisibleForTesting
-        public MmTelCapabilities() {
-            super();
-        }
-
-        public MmTelCapabilities(Capabilities c) {
-            mCapabilities = c.mCapabilities;
-        }
-
-        @IntDef(flag = true,
-                value = {
-                        CAPABILITY_TYPE_VOICE,
-                        CAPABILITY_TYPE_VIDEO,
-                        CAPABILITY_TYPE_UT,
-                        CAPABILITY_TYPE_SMS
-                })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface MmTelCapability {}
-
-        /**
-         * This MmTelFeature supports Voice calling (IR.92)
-         */
-        public static final int CAPABILITY_TYPE_VOICE = 1 << 0;
-
-        /**
-         * This MmTelFeature supports Video (IR.94)
-         */
-        public static final int CAPABILITY_TYPE_VIDEO = 1 << 1;
-
-        /**
-         * This MmTelFeature supports XCAP over Ut for supplementary services. (IR.92)
-         */
-        public static final int CAPABILITY_TYPE_UT = 1 << 2;
-
-        /**
-         * This MmTelFeature supports SMS (IR.92)
-         */
-        public static final int CAPABILITY_TYPE_SMS = 1 << 3;
-
-        @Override
-        public final void addCapabilities(@MmTelCapability int capabilities) {
-            super.addCapabilities(capabilities);
-        }
-
-        @Override
-        public final void removeCapabilities(@MmTelCapability int capability) {
-            super.removeCapabilities(capability);
-        }
-
-        @Override
-        public final boolean isCapable(@MmTelCapability int capabilities) {
-            return super.isCapable(capabilities);
-        }
-    }
-
-    /**
-     * Listener that the framework implements for communication from the MmTelFeature.
-     */
-    public static class Listener extends IImsMmTelListener.Stub {
-
-        @Override
-        public final void onIncomingCall(IImsCallSession c) {
-            onIncomingCall(new ImsCallSession(c));
-        }
-
-        /**
-         * Updates the Listener when the voice message count for IMS has changed.
-         * @param count an integer representing the new message count.
-         */
-        @Override
-        public void onVoiceMessageCountUpdate(int count) {
-
-        }
-
-        /**
-         * Called when the IMS provider receives an incoming call.
-         * @param c The {@link ImsCallSession} associated with the new call.
-         */
-        public void onIncomingCall(ImsCallSession c) {
-        }
-    }
-
-    // Lock for feature synchronization
-    private final Object mLock = new Object();
-    private IImsMmTelListener mListener;
-
-    /**
-     * @param listener A {@link Listener} used when the MmTelFeature receives an incoming call and
-     *     notifies the framework.
-     */
-    private void setListener(IImsMmTelListener listener) {
-        synchronized (mLock) {
-            mListener = listener;
-        }
-    }
-
-    private void queryCapabilityConfigurationInternal(int capability, int radioTech,
-            IImsCapabilityCallback c) {
-        boolean enabled = queryCapabilityConfiguration(capability, radioTech);
-        try {
-            if (c != null) {
-                c.onQueryCapabilityConfiguration(capability, radioTech, enabled);
-            }
-        } catch (RemoteException e) {
-            Log.e(LOG_TAG, "queryCapabilityConfigurationInternal called on dead binder!");
-        }
-    }
-
-    /**
-     * The current capability status that this MmTelFeature has defined is available. This
-     * configuration will be used by the platform to figure out which capabilities are CURRENTLY
-     * available to be used.
-     *
-     * Should be a subset of the capabilities that are enabled by the framework in
-     * {@link #changeEnabledCapabilities}.
-     * @return A copy of the current MmTelFeature capability status.
-     */
-    @Override
-    public final MmTelCapabilities queryCapabilityStatus() {
-        return new MmTelCapabilities(super.queryCapabilityStatus());
-    }
-
-    /**
-     * Notify the framework that the status of the Capabilities has changed. Even though the
-     * MmTelFeature capability may be enabled by the framework, the status may be disabled due to
-     * the feature being unavailable from the network.
-     * @param c The current capability status of the MmTelFeature. If a capability is disabled, then
-     * the status of that capability is disabled. This can happen if the network does not currently
-     * support the capability that is enabled. A capability that is disabled by the framework (via
-     * {@link #changeEnabledCapabilities}) should also show the status as disabled.
-     */
-    protected final void notifyCapabilitiesStatusChanged(MmTelCapabilities c) {
-        super.notifyCapabilitiesStatusChanged(c);
-    }
-
-    /**
-     * Notify the framework of an incoming call.
-     * @param c The {@link ImsCallSession} of the new incoming call.
-     *
-     * @throws RemoteException if the connection to the framework is not available. If this happens,
-     *     the call should be no longer considered active and should be cleaned up.
-     * */
-    protected final void notifyIncomingCall(ImsCallSession c) throws RemoteException {
-        synchronized (mLock) {
-            if (mListener == null) {
-                throw new IllegalStateException("Session is not available.");
-            }
-            mListener.onIncomingCall(c.getSession());
-        }
-    }
-
-    /**
-     * Provides the MmTelFeature with the ability to return the framework Capability Configuration
-     * for a provided Capability. If the framework calls {@link #changeEnabledCapabilities} and
-     * includes a capability A to enable or disable, this method should return the correct enabled
-     * status for capability A.
-     * @param capability The capability that we are querying the configuration for.
-     * @return true if the capability is enabled, false otherwise.
-     */
-    public boolean queryCapabilityConfiguration(@MmTelCapabilities.MmTelCapability int capability,
-            @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
-        // Base implementation - Override to provide functionality
-        return false;
-    }
-
-    /**
-     * The MmTelFeature should override this method to handle the enabling/disabling of
-     * MmTel Features, defined in {@link MmTelCapabilities.MmTelCapability}. The framework assumes
-     * the {@link CapabilityChangeRequest} was processed successfully. If a subset of capabilities
-     * could not be set to their new values,
-     * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError} must be called
-     * individually for each capability whose processing resulted in an error.
-     *
-     * Enabling/Disabling a capability here indicates that the capability should be registered or
-     * deregistered (depending on the capability change) and become available or unavailable to
-     * the framework.
-     */
-    @Override
-    public void changeEnabledCapabilities(CapabilityChangeRequest request,
-            CapabilityCallbackProxy c) {
-        // Base implementation, no-op
-    }
-
-    /**
-     * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
-     *
-     * @param callSessionType a service type that is specified in {@link ImsCallProfile}
-     *        {@link ImsCallProfile#SERVICE_TYPE_NONE}
-     *        {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
-     *        {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
-     * @param callType a call type that is specified in {@link ImsCallProfile}
-     *        {@link ImsCallProfile#CALL_TYPE_VOICE}
-     *        {@link ImsCallProfile#CALL_TYPE_VT}
-     *        {@link ImsCallProfile#CALL_TYPE_VT_TX}
-     *        {@link ImsCallProfile#CALL_TYPE_VT_RX}
-     *        {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
-     *        {@link ImsCallProfile#CALL_TYPE_VS}
-     *        {@link ImsCallProfile#CALL_TYPE_VS_TX}
-     *        {@link ImsCallProfile#CALL_TYPE_VS_RX}
-     * @return a {@link ImsCallProfile} object
-     */
-    public ImsCallProfile createCallProfile(int callSessionType, int callType) {
-        // Base Implementation - Should be overridden
-        return null;
-    }
-
-    /**
-     * Creates an {@link ImsCallSession} with the specified call profile.
-     * Use other methods, if applicable, instead of interacting with
-     * {@link ImsCallSession} directly.
-     *
-     * @param profile a call profile to make the call
-     * @param listener An implementation of IImsCallSessionListener.
-     */
-    public ImsCallSession createCallSession(ImsCallProfile profile,
-            ImsCallSessionListener listener) {
-        // Base Implementation - Should be overridden
-        return null;
-    }
-
-    /**
-     * @return The Ut interface for the supplementary service configuration.
-     */
-    public ImsUtImplBase getUt() {
-        // Base Implementation - Should be overridden
-        return null;
-    }
-
-    /**
-     * @return The Emergency call-back mode interface for emergency VoLTE calls that support it.
-     */
-    public ImsEcbmImplBase getEcbm() {
-        // Base Implementation - Should be overridden
-        return null;
-    }
-
-    /**
-     * @return The Emergency call-back mode interface for emergency VoLTE calls that support it.
-     */
-    public ImsMultiEndpointImplBase getMultiEndpoint() {
-        // Base Implementation - Should be overridden
-        return null;
-    }
-
-    /**
-     * Sets the current UI TTY mode for the MmTelFeature.
-     * @param mode An integer containing the new UI TTY Mode, can consist of
-     *         {@link TelecomManager#TTY_MODE_OFF},
-     *         {@link TelecomManager#TTY_MODE_FULL},
-     *         {@link TelecomManager#TTY_MODE_HCO},
-     *         {@link TelecomManager#TTY_MODE_VCO}
-     * @param onCompleteMessage A {@link Message} to be used when the mode has been set.
-     */
-    void setUiTtyMode(int mode, Message onCompleteMessage) {
-        // Base Implementation - Should be overridden
-    }
-
-    /**{@inheritDoc}*/
-    @Override
-    public void onFeatureRemoved() {
-        // Base Implementation - Should be overridden
-    }
-
-    /**{@inheritDoc}*/
-    @Override
-    public void onFeatureReady() {
-        // Base Implementation - Should be overridden
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public final IImsMmTelFeature getBinder() {
-        return mImsMMTelBinder;
-    }
-}
diff --git a/telephony/java/android/telephony/ims/internal/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/internal/stub/ImsConfigImplBase.java
deleted file mode 100644
index 33aec5d..0000000
--- a/telephony/java/android/telephony/ims/internal/stub/ImsConfigImplBase.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2017 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.internal.stub;
-
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.telephony.ims.internal.aidl.IImsConfig;
-import android.telephony.ims.internal.aidl.IImsConfigCallback;
-
-import com.android.ims.ImsConfig;
-
-/**
- * Controls the modification of IMS specific configurations. For more information on the supported
- * IMS configuration constants, see {@link ImsConfig}.
- *
- * @hide
- */
-
-public class ImsConfigImplBase {
-
-    //TODO: Implement the Binder logic to call base APIs. Need to finish other ImsService Config
-    // work first.
-    private final IImsConfig mBinder = new IImsConfig.Stub() {
-
-        @Override
-        public void addImsConfigCallback(IImsConfigCallback c) throws RemoteException {
-            ImsConfigImplBase.this.addImsConfigCallback(c);
-        }
-
-        @Override
-        public void removeImsConfigCallback(IImsConfigCallback c) throws RemoteException {
-            ImsConfigImplBase.this.removeImsConfigCallback(c);
-        }
-
-        @Override
-        public int getConfigInt(int item) throws RemoteException {
-            return Integer.MIN_VALUE;
-        }
-
-        @Override
-        public String getConfigString(int item) throws RemoteException {
-            return null;
-        }
-
-        @Override
-        public int setConfigInt(int item, int value) throws RemoteException {
-            return Integer.MIN_VALUE;
-        }
-
-        @Override
-        public int setConfigString(int item, String value) throws RemoteException {
-            return Integer.MIN_VALUE;
-        }
-    };
-
-    public class Callback extends IImsConfigCallback.Stub {
-
-        @Override
-        public final void onIntConfigChanged(int item, int value) throws RemoteException {
-            onConfigChanged(item, value);
-        }
-
-        @Override
-        public final void onStringConfigChanged(int item, String value) throws RemoteException {
-            onConfigChanged(item, value);
-        }
-
-        /**
-         * Called when the IMS configuration has changed.
-         * @param item the IMS configuration key constant, as defined in ImsConfig.
-         * @param value the new integer value of the IMS configuration constant.
-         */
-        public void onConfigChanged(int item, int value) {
-            // Base Implementation
-        }
-
-        /**
-         * Called when the IMS configuration has changed.
-         * @param item the IMS configuration key constant, as defined in ImsConfig.
-         * @param value the new String value of the IMS configuration constant.
-         */
-        public void onConfigChanged(int item, String value) {
-            // Base Implementation
-        }
-    }
-
-    private final RemoteCallbackList<IImsConfigCallback> mCallbacks = new RemoteCallbackList<>();
-
-    /**
-     * Adds a {@link Callback} to the list of callbacks notified when a value in the configuration
-     * changes.
-     * @param c callback to add.
-     */
-    private void addImsConfigCallback(IImsConfigCallback c) {
-        mCallbacks.register(c);
-    }
-    /**
-     * Removes a {@link Callback} to the list of callbacks notified when a value in the
-     * configuration changes.
-     *
-     * @param c callback to remove.
-     */
-    private void removeImsConfigCallback(IImsConfigCallback c) {
-        mCallbacks.unregister(c);
-    }
-
-    public final IImsConfig getBinder() {
-        return mBinder;
-    }
-
-    /**
-     * Sets the value for IMS service/capabilities parameters by the operator device
-     * management entity. It sets the config item value in the provisioned storage
-     * from which the master value is derived.
-     *
-     * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
-     * @param value in Integer format.
-     * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
-     */
-    public int setConfig(int item, int value) {
-        // Base Implementation - To be overridden.
-        return ImsConfig.OperationStatusConstants.FAILED;
-    }
-
-    /**
-     * Sets the value for IMS service/capabilities parameters by the operator device
-     * management entity. It sets the config item value in the provisioned storage
-     * from which the master value is derived.
-     *
-     * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
-     * @param value in String format.
-     * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
-     */
-    public int setConfig(int item, String value) {
-        return ImsConfig.OperationStatusConstants.FAILED;
-    }
-
-    /**
-     * Gets the value for ims service/capabilities parameters from the provisioned
-     * value storage.
-     *
-     * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
-     * @return value in Integer format.
-     */
-    public int getConfigInt(int item) {
-        return ImsConfig.OperationStatusConstants.FAILED;
-    }
-
-    /**
-     * Gets the value for ims service/capabilities parameters from the provisioned
-     * value storage.
-     *
-     * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
-     * @return value in String format.
-     */
-    public String getConfigString(int item) {
-        return null;
-    }
-}
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index 80b2f78..c6ca6fd 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -16,105 +16,259 @@
 
 package android.telephony.ims.stub;
 
+import android.annotation.SystemApi;
 import android.os.Message;
 import android.os.RemoteException;
+import android.telephony.ims.ImsCallSessionListener;
+import android.telephony.ims.aidl.IImsCallSessionListener;
 
-import com.android.ims.ImsCallProfile;
-import com.android.ims.ImsStreamMediaProfile;
-import com.android.ims.internal.ImsCallSession;
+import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsStreamMediaProfile;
+import android.telephony.ims.ImsCallSession;
 import com.android.ims.internal.IImsCallSession;
-import com.android.ims.internal.IImsCallSessionListener;
 import com.android.ims.internal.IImsVideoCallProvider;
+import android.telephony.ims.ImsVideoCallProvider;
+
+import dalvik.system.CloseGuard;
 
 /**
- * Base implementation of IImsCallSession, which implements stub versions of the methods in the
- * IImsCallSession AIDL. Override the methods that your implementation of ImsCallSession supports.
+ * Base implementation of IImsCallSession, which implements stub versions of the methods available.
  *
- * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
- * will break other implementations of ImsCallSession maintained by other ImsServices.
+ * Override the methods that your implementation of ImsCallSession supports.
  *
  * @hide
  */
-
-public class ImsCallSessionImplBase extends IImsCallSession.Stub {
+@SystemApi
+// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+// will break other implementations of ImsCallSession maintained by other ImsServices.
+public class ImsCallSessionImplBase implements AutoCloseable {
+    /**
+     * Notify USSD Mode.
+     */
+    public static final int USSD_MODE_NOTIFY = 0;
+    /**
+     * Request USSD Mode
+     */
+    public static final int USSD_MODE_REQUEST = 1;
 
     /**
-     * Closes the object. This object is not usable after being closed.
+     * Defines IMS call session state.
      */
-    @Override
-    public void close() throws RemoteException {
+    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";
+            }
+        }
+
+        /**
+         * @hide
+         */
+        private State() {
+        }
     }
 
-    /**
-     * Gets the call ID of the session.
-     *
-     * @return the call ID
-     */
-    @Override
-    public String getCallId() throws RemoteException {
-        return null;
-    }
+    // Non-final for injection by tests
+    private IImsCallSession mServiceImpl = new IImsCallSession.Stub() {
+        @Override
+        public void close() {
+            ImsCallSessionImplBase.this.close();
+        }
+
+        @Override
+        public String getCallId() {
+            return ImsCallSessionImplBase.this.getCallId();
+        }
+
+        @Override
+        public ImsCallProfile getCallProfile() {
+            return ImsCallSessionImplBase.this.getCallProfile();
+        }
+
+        @Override
+        public ImsCallProfile getLocalCallProfile() {
+            return ImsCallSessionImplBase.this.getLocalCallProfile();
+        }
+
+        @Override
+        public ImsCallProfile getRemoteCallProfile() {
+            return ImsCallSessionImplBase.this.getRemoteCallProfile();
+        }
+
+        @Override
+        public String getProperty(String name) {
+            return ImsCallSessionImplBase.this.getProperty(name);
+        }
+
+        @Override
+        public int getState() {
+            return ImsCallSessionImplBase.this.getState();
+        }
+
+        @Override
+        public boolean isInCall() {
+            return ImsCallSessionImplBase.this.isInCall();
+        }
+
+        @Override
+        public void setListener(IImsCallSessionListener listener) {
+            ImsCallSessionImplBase.this.setListener(new ImsCallSessionListener(listener));
+        }
+
+        @Override
+        public void setMute(boolean muted) {
+            ImsCallSessionImplBase.this.setMute(muted);
+        }
+
+        @Override
+        public void start(String callee, ImsCallProfile profile) {
+            ImsCallSessionImplBase.this.start(callee, profile);
+        }
+
+        @Override
+        public void startConference(String[] participants, ImsCallProfile profile) throws
+                RemoteException {
+            ImsCallSessionImplBase.this.startConference(participants, profile);
+        }
+
+        @Override
+        public void accept(int callType, ImsStreamMediaProfile profile) {
+            ImsCallSessionImplBase.this.accept(callType, profile);
+        }
+
+        @Override
+        public void reject(int reason) {
+            ImsCallSessionImplBase.this.reject(reason);
+        }
+
+        @Override
+        public void terminate(int reason) {
+            ImsCallSessionImplBase.this.terminate(reason);
+        }
+
+        @Override
+        public void hold(ImsStreamMediaProfile profile) {
+            ImsCallSessionImplBase.this.hold(profile);
+        }
+
+        @Override
+        public void resume(ImsStreamMediaProfile profile) {
+            ImsCallSessionImplBase.this.resume(profile);
+        }
+
+        @Override
+        public void merge() {
+            ImsCallSessionImplBase.this.merge();
+        }
+
+        @Override
+        public void update(int callType, ImsStreamMediaProfile profile) {
+            ImsCallSessionImplBase.this.update(callType, profile);
+        }
+
+        @Override
+        public void extendToConference(String[] participants) {
+            ImsCallSessionImplBase.this.extendToConference(participants);
+        }
+
+        @Override
+        public void inviteParticipants(String[] participants) {
+            ImsCallSessionImplBase.this.inviteParticipants(participants);
+        }
+
+        @Override
+        public void removeParticipants(String[] participants) {
+            ImsCallSessionImplBase.this.removeParticipants(participants);
+        }
+
+        @Override
+        public void sendDtmf(char c, Message result) {
+            ImsCallSessionImplBase.this.sendDtmf(c, result);
+        }
+
+        @Override
+        public void startDtmf(char c) {
+            ImsCallSessionImplBase.this.startDtmf(c);
+        }
+
+        @Override
+        public void stopDtmf() {
+            ImsCallSessionImplBase.this.stopDtmf();
+        }
+
+        @Override
+        public void sendUssd(String ussdMessage) {
+            ImsCallSessionImplBase.this.sendUssd(ussdMessage);
+        }
+
+        @Override
+        public IImsVideoCallProvider getVideoCallProvider() {
+            return ImsCallSessionImplBase.this.getVideoCallProvider();
+        }
+
+        @Override
+        public boolean isMultiparty() {
+            return ImsCallSessionImplBase.this.isMultiparty();
+        }
+
+        @Override
+        public void sendRttModifyRequest(ImsCallProfile toProfile) {
+            ImsCallSessionImplBase.this.sendRttModifyRequest(toProfile);
+        }
+
+        @Override
+        public void sendRttModifyResponse(boolean status) {
+            ImsCallSessionImplBase.this.sendRttModifyResponse(status);
+        }
+
+        @Override
+        public void sendRttMessage(String rttMessage) {
+            ImsCallSessionImplBase.this.sendRttMessage(rttMessage);
+        }
+    };
 
     /**
-     * Gets the call profile that this session is associated with
-     *
-     * @return the {@link ImsCallProfile} that this session is associated with
+     * @hide
      */
-    @Override
-    public ImsCallProfile getCallProfile() throws RemoteException {
-        return null;
-    }
-
-    /**
-     * Gets the local call profile that this session is associated with
-     *
-     * @return the local {@link ImsCallProfile} that this session is associated with
-     */
-    @Override
-    public ImsCallProfile getLocalCallProfile() throws RemoteException {
-        return null;
-    }
-
-    /**
-     * Gets the remote call profile that this session is associated with
-     *
-     * @return the remote {@link ImsCallProfile} that this session is associated with
-     */
-    @Override
-    public ImsCallProfile getRemoteCallProfile() throws RemoteException {
-        return null;
-    }
-
-    /**
-     * Gets the value associated with the specified property of this session.
-     *
-     * @return the string value associated with the specified property
-     */
-    @Override
-    public String getProperty(String name) throws RemoteException {
-        return null;
-    }
-
-    /**
-     * Gets the session state.
-     * The value returned must be one of the states in {@link ImsCallSession.State}.
-     *
-     * @return the session state
-     */
-    @Override
-    public int getState() throws RemoteException {
-        return ImsCallSession.State.INVALID;
-    }
-
-    /**
-     * Checks if the session is in call.
-     *
-     * @return true if the session is in call, false otherwise
-     */
-    @Override
-    public boolean isInCall() throws RemoteException {
-        return false;
+    public final void setListener(IImsCallSessionListener listener) throws RemoteException {
+        setListener(new ImsCallSessionListener(listener));
     }
 
     /**
@@ -122,25 +276,87 @@
      * 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
+     * @param listener {@link ImsCallSessionListener} used to notify the framework of updates
+     * to the ImsCallSession
+     */
+    public void setListener(ImsCallSessionListener listener) {
+    }
+
+    /**
+     * Closes the object. This {@link ImsCallSessionImplBase} is not usable after being closed.
      */
     @Override
-    public void setListener(IImsCallSessionListener listener) throws RemoteException {
+    public void close() {
+
+    }
+
+    /**
+     * @return A String containing the unique call ID of this {@link ImsCallSessionImplBase}.
+     */
+    public String getCallId() {
+        return null;
+    }
+
+    /**
+     * @return The {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is associated
+     * with.
+     */
+    public ImsCallProfile getCallProfile() {
+        return null;
+    }
+
+    /**
+     * @return The local {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is
+     * associated with.
+     */
+    public ImsCallProfile getLocalCallProfile() {
+        return null;
+    }
+
+    /**
+     * @return The remote {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is
+     * associated with.
+     */
+    public ImsCallProfile getRemoteCallProfile() {
+        return null;
+    }
+
+    /**
+     * @param name The String extra key.
+     * @return The string extra value associated with the specified property.
+     */
+    public String getProperty(String name) {
+        return null;
+    }
+
+    /**
+     * @return The {@link ImsCallSessionImplBase} state, defined in
+     * {@link ImsCallSessionImplBase.State}.
+     */
+    public int getState() {
+        return ImsCallSessionImplBase.State.INVALID;
+    }
+
+    /**
+     * @return true if the {@link ImsCallSessionImplBase} is in a call, false otherwise.
+     */
+    public boolean isInCall() {
+        return false;
     }
 
     /**
      * Mutes or unmutes the mic for the active call.
      *
-     * @param muted true if the call is muted, false otherwise
+     * @param muted true if the call should be muted, false otherwise.
      */
-    @Override
-    public void setMute(boolean muted) throws RemoteException {
+    public void setMute(boolean muted) {
     }
 
     /**
-     * Initiates an IMS call with the specified target and call profile.
-     * The session listener set in {@link #setListener} is called back upon defined session events.
-     * The method is only valid to call when the session state is in
+     * Initiates an IMS call with the specified number and call profile.
+     * The session listener set in {@link #setListener(ImsCallSessionListener)} is called back upon
+     * defined session events.
+     * Only valid to call when the session state is in
      * {@link ImsCallSession.State#IDLE}.
      *
      * @param callee dialed string to make the call to
@@ -149,13 +365,13 @@
      * @see {@link ImsCallSession.Listener#callSessionStarted},
      * {@link ImsCallSession.Listener#callSessionStartFailed}
      */
-    @Override
-    public void start(String callee, ImsCallProfile profile) throws RemoteException {
+    public void start(String callee, ImsCallProfile profile) {
     }
 
     /**
      * Initiates an IMS call with the specified participants and call profile.
-     * The session listener set in {@link #setListener} is called back upon defined session events.
+     * The session listener set in {@link #setListener(ImsCallSessionListener)} is called back upon
+     * defined session events.
      * The method is only valid to call when the session state is in
      * {@link ImsCallSession.State#IDLE}.
      *
@@ -165,9 +381,7 @@
      * @see {@link ImsCallSession.Listener#callSessionStarted},
      * {@link ImsCallSession.Listener#callSessionStartFailed}
      */
-    @Override
-    public void startConference(String[] participants, ImsCallProfile profile)
-            throws RemoteException {
+    public void startConference(String[] participants, ImsCallProfile profile) {
     }
 
     /**
@@ -177,31 +391,26 @@
      * @param profile stream media profile {@link ImsStreamMediaProfile} to be answered
      * @see {@link ImsCallSession.Listener#callSessionStarted}
      */
-    @Override
-    public void accept(int callType, ImsStreamMediaProfile profile) throws RemoteException {
+    public void accept(int callType, ImsStreamMediaProfile profile) {
     }
 
     /**
      * Rejects an incoming call or session update.
      *
-     * @param reason reason code to reject an incoming call, defined in
-     *         com.android.ims.ImsReasonInfo
+     * @param reason reason code to reject an incoming call, defined in {@link ImsReasonInfo}.
      * {@link ImsCallSession.Listener#callSessionStartFailed}
      */
-    @Override
-    public void reject(int reason) throws RemoteException {
+    public void reject(int reason) {
     }
 
     /**
      * Terminates a call.
      *
-     * @param reason reason code to terminate a call, defined in
-     *         com.android.ims.ImsReasonInfo
+     * @param reason reason code to terminate a call, defined in {@link ImsReasonInfo}.
      *
      * @see {@link ImsCallSession.Listener#callSessionTerminated}
      */
-    @Override
-    public void terminate(int reason) throws RemoteException {
+    public void terminate(int reason) {
     }
 
     /**
@@ -212,8 +421,7 @@
      * @see {@link ImsCallSession.Listener#callSessionHeld},
      * {@link ImsCallSession.Listener#callSessionHoldFailed}
      */
-    @Override
-    public void hold(ImsStreamMediaProfile profile) throws RemoteException {
+    public void hold(ImsStreamMediaProfile profile) {
     }
 
     /**
@@ -224,12 +432,11 @@
      * @see {@link ImsCallSession.Listener#callSessionResumed},
      * {@link ImsCallSession.Listener#callSessionResumeFailed}
      */
-    @Override
-    public void resume(ImsStreamMediaProfile profile) throws RemoteException {
+    public void resume(ImsStreamMediaProfile profile) {
     }
 
     /**
-     * Merges the active & hold call. When the merge starts,
+     * Merges the active and held call. When the merge starts,
      * {@link ImsCallSession.Listener#callSessionMergeStarted} is called.
      * {@link ImsCallSession.Listener#callSessionMergeComplete} is called if the merge is
      * successful, and {@link ImsCallSession.Listener#callSessionMergeFailed} is called if the merge
@@ -239,8 +446,7 @@
      * {@link ImsCallSession.Listener#callSessionMergeComplete},
      *      {@link ImsCallSession.Listener#callSessionMergeFailed}
      */
-    @Override
-    public void merge() throws RemoteException {
+    public void merge() {
     }
 
     /**
@@ -251,8 +457,7 @@
      * @see {@link ImsCallSession.Listener#callSessionUpdated},
      * {@link ImsCallSession.Listener#callSessionUpdateFailed}
      */
-    @Override
-    public void update(int callType, ImsStreamMediaProfile profile) throws RemoteException {
+    public void update(int callType, ImsStreamMediaProfile profile) {
     }
 
     /**
@@ -263,8 +468,7 @@
      * @see {@link ImsCallSession.Listener#callSessionConferenceExtended},
      * {@link ImsCallSession.Listener#callSessionConferenceExtendFailed}
      */
-    @Override
-    public void extendToConference(String[] participants) throws RemoteException {
+    public void extendToConference(String[] participants) {
     }
 
     /**
@@ -274,8 +478,7 @@
      * @see {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestDelivered},
      *      {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestFailed}
      */
-    @Override
-    public void inviteParticipants(String[] participants) throws RemoteException {
+    public void inviteParticipants(String[] participants) {
     }
 
     /**
@@ -285,8 +488,7 @@
      * @see {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestDelivered},
      *      {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestFailed}
      */
-    @Override
-    public void removeParticipants(String[] participants) throws RemoteException {
+    public void removeParticipants(String[] participants) {
     }
 
     /**
@@ -296,8 +498,7 @@
      *
      * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
      */
-    @Override
-    public void sendDtmf(char c, Message result) throws RemoteException {
+    public void sendDtmf(char c, Message result) {
     }
 
     /**
@@ -307,15 +508,13 @@
      *
      * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
      */
-    @Override
-    public void startDtmf(char c) throws RemoteException {
+    public void startDtmf(char c) {
     }
 
     /**
      * Stop a DTMF code.
      */
-    @Override
-    public void stopDtmf() throws RemoteException {
+    public void stopDtmf() {
     }
 
     /**
@@ -323,17 +522,23 @@
      *
      * @param ussdMessage USSD message to send
      */
-    @Override
-    public void sendUssd(String ussdMessage) throws RemoteException {
+    public void sendUssd(String ussdMessage) {
     }
 
     /**
-     * Returns a binder for the video call provider implementation contained within the IMS service
-     * process. This binder is used by the VideoCallProvider subclass in Telephony which
-     * intermediates between the propriety implementation and Telecomm/InCall.
+     * See {@link #getImsVideoCallProvider()}, used directly in older ImsService implementations.
+     * @hide
      */
-    @Override
-    public IImsVideoCallProvider getVideoCallProvider() throws RemoteException {
+    public IImsVideoCallProvider getVideoCallProvider() {
+        ImsVideoCallProvider provider = getImsVideoCallProvider();
+        return provider != null ? provider.getInterface() : null;
+    }
+
+    /**
+     * @return The {@link ImsVideoCallProvider} implementation contained within the IMS service
+     * process.
+     */
+    public ImsVideoCallProvider getImsVideoCallProvider() {
         return null;
     }
 
@@ -341,8 +546,7 @@
      * Determines if the current session is multiparty.
      * @return {@code True} if the session is multiparty.
      */
-    @Override
-    public boolean isMultiparty() throws RemoteException {
+    public boolean isMultiparty() {
         return false;
     }
 
@@ -350,16 +554,13 @@
      * Device issues RTT modify request
      * @param toProfile The profile with requested changes made
      */
-    @Override
     public void sendRttModifyRequest(ImsCallProfile toProfile) {
     }
 
     /**
      * Device responds to Remote RTT modify request
-     * @param status true  Accepted the request
-     *                false  Declined the request
+     * @param status true if the the request was accepted or false of the request is defined.
      */
-    @Override
     public void sendRttModifyResponse(boolean status) {
     }
 
@@ -367,7 +568,16 @@
      * Device sends RTT message
      * @param rttMessage RTT message to be sent
      */
-    @Override
     public void sendRttMessage(String rttMessage) {
     }
+
+    /** @hide */
+    public IImsCallSession getServiceImpl() {
+        return mServiceImpl;
+    }
+
+    /** @hide */
+    public void setServiceImpl(IImsCallSession serviceImpl) {
+        mServiceImpl = serviceImpl;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionListenerImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionListenerImplBase.java
deleted file mode 100644
index 6c18935..0000000
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionListenerImplBase.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2017 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.stub;
-
-import com.android.ims.ImsCallProfile;
-import com.android.ims.ImsConferenceState;
-import com.android.ims.ImsReasonInfo;
-import com.android.ims.ImsStreamMediaProfile;
-import com.android.ims.ImsSuppServiceNotification;
-import com.android.ims.internal.IImsCallSession;
-import com.android.ims.internal.IImsCallSessionListener;
-
-/**
- * Base implementation of ImsCallSessionListenerBase, which implements stub versions of the methods
- * in the IImsCallSessionListener AIDL. Override the methods that your implementation of
- * ImsCallSessionListener supports.
- *
- * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
- * will break other implementations of ImsCallSessionListener maintained by other ImsServices.
- *
- * @hide
- */
-public class ImsCallSessionListenerImplBase extends IImsCallSessionListener.Stub {
-    /**
-     * Notifies the result of the basic session operation (setup / terminate).
-     */
-    @Override
-    public void callSessionProgressing(IImsCallSession session, ImsStreamMediaProfile profile) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionStarted(IImsCallSession session, ImsCallProfile profile) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionStartFailed(IImsCallSession session, ImsReasonInfo reasonInfo) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionTerminated(IImsCallSession session, ImsReasonInfo reasonInfo) {
-        // no-op
-    }
-
-    /**
-     * Notifies the result of the call hold/resume operation.
-     */
-    @Override
-    public void callSessionHeld(IImsCallSession session, ImsCallProfile profile) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionHoldFailed(IImsCallSession session, ImsReasonInfo reasonInfo) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionHoldReceived(IImsCallSession session, ImsCallProfile profile) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionResumed(IImsCallSession session, ImsCallProfile profile) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionResumeFailed(IImsCallSession session, ImsReasonInfo reasonInfo) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionResumeReceived(IImsCallSession session, ImsCallProfile profile) {
-        // no-op
-    }
-
-    /**
-     * Notifies the result of call merge operation.
-     */
-    @Override
-    public void callSessionMergeStarted(IImsCallSession session, IImsCallSession newSession,
-            ImsCallProfile profile) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionMergeComplete(IImsCallSession session) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionMergeFailed(IImsCallSession session, ImsReasonInfo reasonInfo) {
-        // no-op
-    }
-
-    /**
-     * Notifies the result of call upgrade / downgrade or any other call
-     * updates.
-     */
-    @Override
-    public void callSessionUpdated(IImsCallSession session, ImsCallProfile profile) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionUpdateFailed(IImsCallSession session, ImsReasonInfo reasonInfo) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionUpdateReceived(IImsCallSession session, ImsCallProfile profile) {
-        // no-op
-    }
-
-    /**
-     * Notifies the result of conference extension.
-     */
-    @Override
-    public void callSessionConferenceExtended(IImsCallSession session, IImsCallSession newSession,
-            ImsCallProfile profile) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionConferenceExtendFailed(IImsCallSession session,
-            ImsReasonInfo reasonInfo) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionConferenceExtendReceived(IImsCallSession session,
-            IImsCallSession newSession,
-            ImsCallProfile profile) {
-        // no-op
-    }
-
-    /**
-     * Notifies the result of the participant invitation / removal to/from the
-     * conference session.
-     */
-    @Override
-    public void callSessionInviteParticipantsRequestDelivered(IImsCallSession session) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionInviteParticipantsRequestFailed(IImsCallSession session,
-            ImsReasonInfo reasonInfo) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionRemoveParticipantsRequestDelivered(IImsCallSession session) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionRemoveParticipantsRequestFailed(IImsCallSession session,
-            ImsReasonInfo reasonInfo) {
-        // no-op
-    }
-
-    /**
-     * Notifies the changes of the conference info. the conference session.
-     */
-    @Override
-    public void callSessionConferenceStateUpdated(IImsCallSession session,
-            ImsConferenceState state) {
-        // no-op
-    }
-
-    /**
-     * Notifies the incoming USSD message.
-     */
-    @Override
-    public void callSessionUssdMessageReceived(IImsCallSession session, int mode,
-            String ussdMessage) {
-        // no-op
-    }
-
-    /**
-     * Notifies of a case where a {@link com.android.ims.internal.ImsCallSession} may potentially
-     * handover from one radio technology to another.
-     * @param session
-     * @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(IImsCallSession session, int srcAccessTech,
-            int targetAccessTech) {
-        // no-op
-    }
-
-    /**
-     * Notifies of handover information for this call
-     */
-    @Override
-    public void callSessionHandover(IImsCallSession session, int srcAccessTech,
-            int targetAccessTech,
-            ImsReasonInfo reasonInfo) {
-        // no-op
-    }
-
-    @Override
-    public void callSessionHandoverFailed(IImsCallSession session, int srcAccessTech,
-            int targetAccessTech,
-            ImsReasonInfo reasonInfo) {
-        // no-op
-    }
-
-    /**
-     * Notifies the TTY mode change by remote party.
-     *
-     * @param mode one of the following: -
-     *            {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} -
-     *            {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} -
-     *            {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} -
-     *            {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
-     */
-    @Override
-    public void callSessionTtyModeReceived(IImsCallSession 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.
-     */
-    @Override
-    public void callSessionMultipartyStateChanged(IImsCallSession session, boolean isMultiParty) {
-        // no-op
-    }
-
-    /**
-     * Notifies the supplementary service information for the current session.
-     */
-    @Override
-    public void callSessionSuppServiceReceived(IImsCallSession session,
-            ImsSuppServiceNotification suppSrvNotification) {
-        // no-op
-    }
-
-    /**
-     * Received RTT modify request from Remote Party
-     * @param session The call session.
-     * @param callProfile ImsCallProfile with updated attribute
-     */
-    @Override
-    public void callSessionRttModifyRequestReceived(IImsCallSession session,
-            ImsCallProfile callProfile) {
-        // no-op
-    }
-
-    /**
-     * Received response for RTT modify request
-     * @param status true : Accepted the request
-     *               false : Declined the request
-     */
-    @Override
-    public void callSessionRttModifyResponseReceived(int status) {
-        // no -op
-    }
-
-    /**
-     * Device received RTT message from Remote UE
-     * @param rttMessage RTT message received
-     */
-    @Override
-    public void callSessionRttMessageReceived(String rttMessage) {
-        // no-op
-    }
-}
-
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index 5a4db99..c6e5ddb 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -16,135 +16,400 @@
 
 package android.telephony.ims.stub;
 
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsConfigCallback;
+import android.util.Log;
 
 import com.android.ims.ImsConfig;
-import com.android.ims.ImsConfigListener;
-import com.android.ims.internal.IImsConfig;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
 
 /**
- * Base implementation of ImsConfig, which implements stub versions of the methods
- * in the IImsConfig AIDL. Override the methods that your implementation of ImsConfig supports.
+ * Controls the modification of IMS specific configurations. For more information on the supported
+ * IMS configuration constants, see {@link ImsConfig}.
  *
- * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
- * will break other implementations of ImsConfig maintained by other ImsServices.
- *
- * Provides APIs to get/set the IMS service feature/capability/parameters.
- * The config items include:
- * 1) Items provisioned by the operator.
- * 2) Items configured by user. Mainly service feature class.
- *
+ * The inner class {@link ImsConfigStub} implements methods of IImsConfig AIDL interface.
+ * The IImsConfig AIDL interface is called by ImsConfig, which may exist in many other processes.
+ * ImsConfigImpl access to the configuration parameters may be arbitrarily slow, especially in
+ * during initialization, or times when a lot of configuration parameters are being set/get
+ * (such as during boot up or SIM card change). By providing a cache in ImsConfigStub, we can speed
+ * up access to these configuration parameters, so a query to the ImsConfigImpl does not have to be
+ * performed every time.
  * @hide
  */
+@SystemApi
+public class ImsConfigImplBase {
 
-public class ImsConfigImplBase extends IImsConfig.Stub {
+    private static final String TAG = "ImsConfigImplBase";
 
     /**
-     * Gets the value for ims service/capabilities parameters from the provisioned
-     * value storage. Synchronous blocking call.
+     * Implements the IImsConfig AIDL interface, which is called by potentially many processes
+     * in order to get/set configuration parameters.
      *
-     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
-     * @return value in Integer format.
+     * It holds an object of ImsConfigImplBase class which is usually extended by ImsConfigImpl
+     * with actual implementations from vendors. This class caches provisioned values from
+     * ImsConfigImpl layer because queries through ImsConfigImpl can be slow. When query goes in,
+     * it first checks cache layer. If missed, it will call the vendor implementation of
+     * ImsConfigImplBase API.
+     * and cache the return value if the set succeeds.
+     *
+     * Provides APIs to get/set the IMS service feature/capability/parameters.
+     * The config items include:
+     * 1) Items provisioned by the operator.
+     * 2) Items configured by user. Mainly service feature class.
+     *
+     * @hide
      */
-    @Override
-    public int getProvisionedValue(int item) throws RemoteException {
-        return -1;
+    @VisibleForTesting
+    static public class ImsConfigStub extends IImsConfig.Stub {
+        WeakReference<ImsConfigImplBase> mImsConfigImplBaseWeakReference;
+        private HashMap<Integer, Integer> mProvisionedIntValue = new HashMap<>();
+        private HashMap<Integer, String> mProvisionedStringValue = new HashMap<>();
+
+        @VisibleForTesting
+        public ImsConfigStub(ImsConfigImplBase imsConfigImplBase) {
+            mImsConfigImplBaseWeakReference =
+                    new WeakReference<ImsConfigImplBase>(imsConfigImplBase);
+        }
+
+        @Override
+        public void addImsConfigCallback(IImsConfigCallback c) throws RemoteException {
+            getImsConfigImpl().addImsConfigCallback(c);
+        }
+
+        @Override
+        public void removeImsConfigCallback(IImsConfigCallback c) throws RemoteException {
+            getImsConfigImpl().removeImsConfigCallback(c);
+        }
+
+        /**
+         * Gets the value for ims service/capabilities parameters. It first checks its local cache,
+         * if missed, it will call ImsConfigImplBase.getConfigInt.
+         * Synchronous blocking call.
+         *
+         * @param item integer key
+         * @return value in Integer format or {@link #CONFIG_RESULT_UNKNOWN} if
+         * unavailable.
+         */
+        @Override
+        public synchronized int getConfigInt(int item) throws RemoteException {
+            if (mProvisionedIntValue.containsKey(item)) {
+                return mProvisionedIntValue.get(item);
+            } else {
+                int retVal = getImsConfigImpl().getConfigInt(item);
+                if (retVal != ImsConfig.OperationStatusConstants.UNKNOWN) {
+                    updateCachedValue(item, retVal, false);
+                }
+                return retVal;
+            }
+        }
+
+        /**
+         * Gets the value for ims service/capabilities parameters. It first checks its local cache,
+         * if missed, it will call #ImsConfigImplBase.getConfigString.
+         * Synchronous blocking call.
+         *
+         * @param item integer key
+         * @return value in String format.
+         */
+        @Override
+        public synchronized String getConfigString(int item) throws RemoteException {
+            if (mProvisionedIntValue.containsKey(item)) {
+                return mProvisionedStringValue.get(item);
+            } else {
+                String retVal = getImsConfigImpl().getConfigString(item);
+                if (retVal != null) {
+                    updateCachedValue(item, retVal, false);
+                }
+                return retVal;
+            }
+        }
+
+        /**
+         * Sets the value for IMS service/capabilities parameters by the operator device
+         * management entity. It sets the config item value in the provisioned storage
+         * from which the master value is derived, and write it into local cache.
+         * Synchronous blocking call.
+         *
+         * @param item integer key
+         * @param value in Integer format.
+         * @return the result of setting the configuration value, defined as either
+         * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
+         */
+        @Override
+        public synchronized int setConfigInt(int item, int value) throws RemoteException {
+            mProvisionedIntValue.remove(item);
+            int retVal = getImsConfigImpl().setConfig(item, value);
+            if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+                updateCachedValue(item, value, true);
+            } else {
+                Log.d(TAG, "Set provision value of " + item +
+                        " to " + value + " failed with error code " + retVal);
+            }
+
+            return retVal;
+        }
+
+        /**
+         * Sets the value for IMS service/capabilities parameters by the operator device
+         * management entity. It sets the config item value in the provisioned storage
+         * from which the master value is derived, and write it into local cache.
+         * Synchronous blocking call.
+         *
+         * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
+         * @param value in String format.
+         * @return the result of setting the configuration value, defined as either
+         * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
+         */
+        @Override
+        public synchronized int setConfigString(int item, String value)
+                throws RemoteException {
+            mProvisionedStringValue.remove(item);
+            int retVal = getImsConfigImpl().setConfig(item, value);
+            if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+                updateCachedValue(item, value, true);
+            }
+
+            return retVal;
+        }
+
+        private ImsConfigImplBase getImsConfigImpl() throws RemoteException {
+            ImsConfigImplBase ref = mImsConfigImplBaseWeakReference.get();
+            if (ref == null) {
+                throw new RemoteException("Fail to get ImsConfigImpl");
+            } else {
+                return ref;
+            }
+        }
+
+        private void notifyImsConfigChanged(int item, int value) throws RemoteException {
+            getImsConfigImpl().notifyConfigChanged(item, value);
+        }
+
+        private void notifyImsConfigChanged(int item, String value) throws RemoteException {
+            getImsConfigImpl().notifyConfigChanged(item, value);
+        }
+
+        protected synchronized void updateCachedValue(int item, int value, boolean notifyChange)
+                throws RemoteException {
+            mProvisionedIntValue.put(item, value);
+            if (notifyChange) {
+                notifyImsConfigChanged(item, value);
+            }
+        }
+
+        protected synchronized void updateCachedValue(int item, String value,
+                boolean notifyChange) throws RemoteException {
+            mProvisionedStringValue.put(item, value);
+            if (notifyChange) {
+                notifyImsConfigChanged(item, value);
+            }
+        }
     }
 
     /**
-     * Gets the value for ims service/capabilities parameters from the provisioned
-     * value storage. Synchronous blocking call.
-     *
-     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
-     * @return value in String format.
+     * Callback that the framework uses for receiving Configuration change updates.
+     * {@hide}
      */
-    @Override
-    public String getProvisionedStringValue(int item) throws RemoteException {
+    public static class Callback extends IImsConfigCallback.Stub {
+
+        @Override
+        public final void onIntConfigChanged(int item, int value) throws RemoteException {
+            onConfigChanged(item, value);
+        }
+
+        @Override
+        public final void onStringConfigChanged(int item, String value) throws RemoteException {
+            onConfigChanged(item, value);
+        }
+
+        /**
+         * Called when the IMS configuration has changed.
+         * @param item the IMS configuration key constant, as defined in ImsConfig.
+         * @param value the new integer value of the IMS configuration constant.
+         */
+        public void onConfigChanged(int item, int value) {
+            // Base Implementation
+        }
+
+        /**
+         * Called when the IMS configuration has changed.
+         * @param item the IMS configuration key constant, as defined in ImsConfig.
+         * @param value the new String value of the IMS configuration constant.
+         */
+        public void onConfigChanged(int item, String value) {
+            // Base Implementation
+        }
+    }
+
+    /**
+     * The configuration requested resulted in an unknown result. This may happen if the
+     * IMS configurations are unavailable.
+     */
+    public static final int CONFIG_RESULT_UNKNOWN = -1;
+    /**
+     * Setting the configuration value completed.
+     */
+    public static final int CONFIG_RESULT_SUCCESS = 0;
+    /**
+     * Setting the configuration value failed.
+     */
+    public static final int CONFIG_RESULT_FAILED =  1;
+
+    private final RemoteCallbackList<IImsConfigCallback> mCallbacks = new RemoteCallbackList<>();
+    ImsConfigStub mImsConfigStub;
+
+    /**
+     * Used for compatibility between older versions of the ImsService.
+     * @hide
+     */
+    public ImsConfigImplBase(Context context) {
+        mImsConfigStub = new ImsConfigStub(this);
+    }
+
+    public ImsConfigImplBase() {
+        mImsConfigStub = new ImsConfigStub(this);
+    }
+
+    /**
+     * Adds a {@link Callback} to the list of callbacks notified when a value in the configuration
+     * changes.
+     * @param c callback to add.
+     */
+    private void addImsConfigCallback(IImsConfigCallback c) {
+        mCallbacks.register(c);
+    }
+    /**
+     * Removes a {@link Callback} to the list of callbacks notified when a value in the
+     * configuration changes.
+     *
+     * @param c callback to remove.
+     */
+    private void removeImsConfigCallback(IImsConfigCallback c) {
+        mCallbacks.unregister(c);
+    }
+
+    /**
+     * @param item
+     * @param value
+     */
+    private final void notifyConfigChanged(int item, int value) {
+        // can be null in testing
+        if (mCallbacks == null) {
+            return;
+        }
+        mCallbacks.broadcast(c -> {
+            try {
+                c.onIntConfigChanged(item, value);
+            } catch (RemoteException e) {
+                Log.w(TAG, "notifyConfigChanged(int): dead binder in notify, skipping.");
+            }
+        });
+    }
+
+    private void notifyConfigChanged(int item, String value) {
+        // can be null in testing
+        if (mCallbacks == null) {
+            return;
+        }
+        mCallbacks.broadcast(c -> {
+            try {
+                c.onStringConfigChanged(item, value);
+            } catch (RemoteException e) {
+                Log.w(TAG, "notifyConfigChanged(string): dead binder in notify, skipping.");
+            }
+        });
+    }
+
+    /**
+     * @hide
+     */
+    public IImsConfig getIImsConfig() { return mImsConfigStub; }
+
+    /**
+     * Updates provisioning value and notifies the framework of the change.
+     * Doesn't call {@link #setConfig(int,int)} and assumes the result succeeded.
+     * This should only be used when the IMS implementer implicitly changed provisioned values.
+     *
+     * @param item an integer key.
+     * @param value in Integer format.
+     */
+    public final void notifyProvisionedValueChanged(int item, int value) {
+        try {
+            mImsConfigStub.updateCachedValue(item, value, true);
+        } catch (RemoteException e) {
+            Log.w(TAG, "notifyProvisionedValueChanged(int): Framework connection is dead.");
+        }
+    }
+
+    /**
+     * Updates provisioning value and notifies the framework of the change.
+     * Doesn't call {@link #setConfig(int,String)} and assumes the result succeeded.
+     * This should only be used when the IMS implementer implicitly changed provisioned values.
+     *
+     * @param item an integer key.
+     * @param value in String format.
+     */
+    public final void notifyProvisionedValueChanged(int item, String value) {
+        try {
+            mImsConfigStub.updateCachedValue(item, value, true);
+        } catch (RemoteException e) {
+            Log.w(TAG, "notifyProvisionedValueChanged(string): Framework connection is dead.");
+        }
+    }
+
+    /**
+     * Sets the configuration value for this ImsService.
+     *
+     * @param item an integer key.
+     * @param value an integer containing the configuration value.
+     * @return the result of setting the configuration value, defined as either
+     * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
+     */
+    public int setConfig(int item, int value) {
+        // Base Implementation - To be overridden.
+        return CONFIG_RESULT_FAILED;
+    }
+
+    /**
+     * Sets the configuration value for this ImsService.
+     *
+     * @param item an integer key.
+     * @param value a String containing the new configuration value.
+     * @return Result of setting the configuration value, defined as either
+     * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
+     */
+    public int setConfig(int item, String value) {
+        // Base Implementation - To be overridden.
+        return CONFIG_RESULT_FAILED;
+    }
+
+    /**
+     * Gets the currently stored value configuration value from the ImsService for {@code item}.
+     *
+     * @param item an integer key.
+     * @return configuration value, stored in integer format or {@link #CONFIG_RESULT_UNKNOWN} if
+     * unavailable.
+     */
+    public int getConfigInt(int item) {
+        // Base Implementation - To be overridden.
+        return CONFIG_RESULT_UNKNOWN;
+    }
+
+    /**
+     * Gets the currently stored value configuration value from the ImsService for {@code item}.
+     *
+     * @param item an integer key.
+     * @return configuration value, stored in String format or {@code null} if unavailable.
+     */
+    public String getConfigString(int item) {
+        // Base Implementation - To be overridden.
         return null;
     }
-
-    /**
-     * Sets the value for IMS service/capabilities parameters by the operator device
-     * management entity. It sets the config item value in the provisioned storage
-     * from which the master value is derived. Synchronous blocking call.
-     *
-     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
-     * @param value in Integer format.
-     * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
-     */
-    @Override
-    public int setProvisionedValue(int item, int value) throws RemoteException {
-        return ImsConfig.OperationStatusConstants.FAILED;
-    }
-
-    /**
-     * Sets the value for IMS service/capabilities parameters by the operator device
-     * management entity. It sets the config item value in the provisioned storage
-     * from which the master value is derived.  Synchronous blocking call.
-     *
-     * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
-     * @param value in String format.
-     * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
-     */
-    @Override
-    public int setProvisionedStringValue(int item, String value) throws RemoteException {
-        return ImsConfig.OperationStatusConstants.FAILED;
-    }
-
-    /**
-     * Gets the value of the specified IMS feature item for specified network type.
-     * This operation gets the feature config value from the master storage (i.e. final
-     * value). Asynchronous non-blocking call.
-     *
-     * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants.
-     * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
-     * @param listener feature value returned asynchronously through listener.
-     */
-    @Override
-    public void getFeatureValue(int feature, int network, ImsConfigListener listener)
-            throws RemoteException {
-    }
-
-    /**
-     * Sets the value for IMS feature item for specified network type.
-     * This operation stores the user setting in setting db from which master db
-     * is derived.
-     *
-     * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants.
-     * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
-     * @param value as defined in com.android.ims.ImsConfig#FeatureValueConstants.
-     * @param listener, provided if caller needs to be notified for set result.
-     */
-    @Override
-    public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener)
-            throws RemoteException {
-    }
-
-    /**
-     * Gets the value for IMS VoLTE provisioned.
-     * This should be the same as the operator provisioned value if applies.
-     */
-    @Override
-    public boolean getVolteProvisioned() throws RemoteException {
-        return false;
-    }
-
-    /**
-     * Gets the value for IMS feature item video quality.
-     *
-     * @param listener Video quality value returned asynchronously through listener.
-     */
-    @Override
-    public void getVideoQuality(ImsConfigListener listener) throws RemoteException {
-    }
-
-    /**
-     * 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.
-     */
-    @Override
-    public void setVideoQuality(int quality, ImsConfigListener listener) throws RemoteException {
-    }
-}
+}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
index 89f95ff..06c35ea 100644
--- a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
@@ -16,7 +16,9 @@
 
 package android.telephony.ims.stub;
 
+import android.annotation.SystemApi;
 import android.os.RemoteException;
+import android.util.Log;
 
 import com.android.ims.internal.IImsEcbm;
 import com.android.ims.internal.IImsEcbmListener;
@@ -30,22 +32,65 @@
  *
  * @hide
  */
+@SystemApi
+public class ImsEcbmImplBase {
+    private static final String TAG = "ImsEcbmImplBase";
 
-public class ImsEcbmImplBase extends IImsEcbm.Stub {
+    private IImsEcbmListener mListener;
+    private IImsEcbm mImsEcbm = new IImsEcbm.Stub() {
+        @Override
+        public void setListener(IImsEcbmListener listener) {
+            mListener = listener;
+        }
 
-    /**
-     * Sets the listener.
-     */
-    @Override
-    public void setListener(IImsEcbmListener listener) throws RemoteException {
+        @Override
+        public void exitEmergencyCallbackMode() {
+            ImsEcbmImplBase.this.exitEmergencyCallbackMode();
+        }
+    };
 
+    /** @hide */
+    public IImsEcbm getImsEcbm() {
+        return mImsEcbm;
     }
 
     /**
-     * Requests Modem to come out of ECBM mode
+     * This method should be implemented by the IMS provider. Framework will trigger this method to
+     * request to come out of ECBM mode
      */
-    @Override
-    public void exitEmergencyCallbackMode() throws RemoteException {
+    public void exitEmergencyCallbackMode() {
+        Log.d(TAG, "exitEmergencyCallbackMode() not implemented");
+    }
 
+    /**
+     * Notifies the framework when the device enters Emergency Callback Mode.
+     *
+     * @throws RuntimeException if the connection to the framework is not available.
+     */
+    public final void enteredEcbm() {
+        Log.d(TAG, "Entered ECBM.");
+        if (mListener != null) {
+            try {
+                mListener.enteredECBM();
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    /**
+     * Notifies the framework when the device exits Emergency Callback Mode.
+     *
+     * @throws RuntimeException if the connection to the framework is not available.
+     */
+    public final void exitedEcbm() {
+        Log.d(TAG, "Exited ECBM.");
+        if (mListener != null) {
+            try {
+                mListener.exitedECBM();
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
     }
 }
diff --git a/telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.aidl b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.aidl
similarity index 93%
rename from telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.aidl
rename to telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.aidl
index e890cf8..e2ae0e8 100644
--- a/telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.aidl
+++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.aidl
@@ -14,6 +14,6 @@
  * limitations under the License
  */
 
-package android.telephony.ims.internal.stub;
+package android.telephony.ims.stub;
 
 parcelable ImsFeatureConfiguration;
diff --git a/telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.java b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
similarity index 77%
rename from telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.java
rename to telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
index 244c957..98b67c3 100644
--- a/telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.java
+++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,29 +14,34 @@
  * limitations under the License
  */
 
-package android.telephony.ims.internal.stub;
+package android.telephony.ims.stub;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.telephony.ims.internal.feature.ImsFeature;
+import android.telephony.ims.feature.ImsFeature;
 import android.util.ArraySet;
 
-import java.util.Arrays;
 import java.util.Set;
 
 /**
  * Container class for IMS Feature configuration. This class contains the features that the
- * ImsService supports, which are defined in {@link ImsFeature.FeatureType}.
+ * ImsService supports, which are defined in {@link ImsFeature} as
+ * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+ * {@link ImsFeature#FEATURE_RCS}.
+ *
  * @hide
  */
-public class ImsFeatureConfiguration implements Parcelable {
+@SystemApi
+public final class ImsFeatureConfiguration implements Parcelable {
     /**
      * Features that this ImsService supports.
      */
     private final Set<Integer> mFeatures;
 
     /**
-     * Creates an ImsFeatureConfiguration with the features
+     * Builder for {@link ImsFeatureConfiguration} that makes adding supported {@link ImsFeature}s
+     * easier.
      */
     public static class Builder {
             ImsFeatureConfiguration mConfig;
@@ -72,7 +77,10 @@
      * Configuration of the ImsService, which describes which features the ImsService supports
      * (for registration).
      * @param features an array of feature integers defined in {@link ImsFeature} that describe
-     * which features this ImsService supports.
+     * which features this ImsService supports. Supported values are
+     * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+     * {@link ImsFeature#FEATURE_RCS}.
+     * @hide
      */
     public ImsFeatureConfiguration(int[] features) {
         mFeatures = new ArraySet<>();
@@ -85,7 +93,9 @@
     }
 
     /**
-     * @return an int[] containing the features that this ImsService supports.
+     * @return an int[] containing the features that this ImsService supports. Supported values are
+     * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+     * {@link ImsFeature#FEATURE_RCS}.
      */
     public int[] getServiceFeatures() {
         return mFeatures.stream().mapToInt(i->i).toArray();
@@ -95,6 +105,7 @@
         mFeatures.add(feature);
     }
 
+    /** @hide */
     protected ImsFeatureConfiguration(Parcel in) {
         int[] features = in.createIntArray();
         if (features != null) {
@@ -130,16 +141,23 @@
         dest.writeIntArray(mFeatures.stream().mapToInt(i->i).toArray());
     }
 
+    /**
+     * @hide
+     */
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
         if (!(o instanceof ImsFeatureConfiguration)) return false;
 
-        ImsFeatureConfiguration that = (ImsFeatureConfiguration) o;
+        ImsFeatureConfiguration
+                that = (ImsFeatureConfiguration) o;
 
         return mFeatures.equals(that.mFeatures);
     }
 
+    /**
+     * @hide
+     */
     @Override
     public int hashCode() {
         return mFeatures.hashCode();
diff --git a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
index 05da9da..ce2d89a 100644
--- a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
@@ -16,11 +16,16 @@
 
 package android.telephony.ims.stub;
 
+import android.annotation.SystemApi;
 import android.os.RemoteException;
+import android.util.Log;
 
+import android.telephony.ims.ImsExternalCallState;
 import com.android.ims.internal.IImsExternalCallStateListener;
 import com.android.ims.internal.IImsMultiEndpoint;
 
+import java.util.List;
+
 /**
  * Base implementation of ImsMultiEndpoint, which implements stub versions of the methods
  * in the IImsMultiEndpoint AIDL. Override the methods that your implementation of
@@ -31,23 +36,49 @@
  *
  * @hide
  */
+@SystemApi
+public class ImsMultiEndpointImplBase {
+    private static final String TAG = "MultiEndpointImplBase";
 
-public class ImsMultiEndpointImplBase extends IImsMultiEndpoint.Stub {
+    private IImsExternalCallStateListener mListener;
+    private IImsMultiEndpoint mImsMultiEndpoint = new IImsMultiEndpoint.Stub() {
+        @Override
+        public void setListener(IImsExternalCallStateListener listener) throws RemoteException {
+            mListener = listener;
+        }
 
-    /**
-     * Sets the listener.
-     */
-    @Override
-    public void setListener(IImsExternalCallStateListener listener) throws RemoteException {
+        @Override
+        public void requestImsExternalCallStateInfo() throws RemoteException {
+            ImsMultiEndpointImplBase.this.requestImsExternalCallStateInfo();
+        }
+    };
 
+    /** @hide */
+    public IImsMultiEndpoint getIImsMultiEndpoint() {
+        return mImsMultiEndpoint;
     }
 
     /**
-     * Query API to get the latest Dialog Event Package information
-     * Should be invoked only after setListener is done
+     * Notifies framework when Dialog Event Package update is received
+     *
+     * @throws RuntimeException if the connection to the framework is not available.
      */
-    @Override
-    public void requestImsExternalCallStateInfo() throws RemoteException {
+    public final void onImsExternalCallStateUpdate(List<ImsExternalCallState> externalCallDialogs) {
+        Log.d(TAG, "ims external call state update triggered.");
+        if (mListener != null) {
+            try {
+                mListener.onImsExternalCallStateUpdate(externalCallDialogs);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
 
+    /**
+     * This method should be implemented by the IMS provider. Framework will trigger this to get the
+     * latest Dialog Event Package information. Should
+     */
+    public void requestImsExternalCallStateInfo() {
+        Log.d(TAG, "requestImsExternalCallStateInfo() not implemented");
     }
 }
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index 42af083..4334d3a 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -17,15 +17,16 @@
 package android.telephony.ims.stub;
 
 import android.annotation.IntDef;
+import android.annotation.SystemApi;
 import android.net.Uri;
-import android.os.IBinder;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.aidl.IImsRegistrationCallback;
 import android.util.Log;
 
-import com.android.ims.ImsReasonInfo;
-import com.android.ims.internal.IImsRegistration;
-import com.android.ims.internal.IImsRegistrationCallback;
+import android.telephony.ims.ImsReasonInfo;
+
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.lang.annotation.Retention;
@@ -36,11 +37,14 @@
  * registration for this ImsService has changed status.
  * @hide
  */
-
+@SystemApi
 public class ImsRegistrationImplBase {
 
     private static final String LOG_TAG = "ImsRegistrationImplBase";
 
+    /**
+     * @hide
+     */
     // Defines the underlying radio technology type that we have registered for IMS over.
     @IntDef(flag = true,
             value = {
@@ -155,6 +159,9 @@
     // Locked on mLock, create unspecified disconnect cause.
     private ImsReasonInfo mLastDisconnectCause = new ImsReasonInfo();
 
+    /**
+     * @hide
+     */
     public final IImsRegistration getBinder() {
         return mBinder;
     }
@@ -171,8 +178,8 @@
     /**
      * Notify the framework that the device is connected to the IMS network.
      *
-     * @param imsRadioTech the radio access technology. Valid values are defined in
-     * {@link ImsRegistrationTech}.
+     * @param imsRadioTech the radio access technology. Valid values are defined as
+     * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}.
      */
     public final void onRegistered(@ImsRegistrationTech int imsRadioTech) {
         updateToState(imsRadioTech, REGISTRATION_STATE_REGISTERED);
@@ -189,8 +196,8 @@
     /**
      * Notify the framework that the device is trying to connect the IMS network.
      *
-     * @param imsRadioTech the radio access technology. Valid values are defined in
-     * {@link ImsRegistrationTech}.
+     * @param imsRadioTech the radio access technology. Valid values are defined as
+     * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}.
      */
     public final void onRegistering(@ImsRegistrationTech int imsRadioTech) {
         updateToState(imsRadioTech, REGISTRATION_STATE_REGISTERING);
@@ -221,6 +228,13 @@
         });
     }
 
+    /**
+     * Notify the framework that the handover from the current radio technology to the technology
+     * defined in {@code imsRadioTech} has failed.
+     * @param imsRadioTech The technology that has failed to be changed. Valid values are
+     * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}.
+     * @param info The {@link ImsReasonInfo} for the failure to change technology.
+     */
     public final void onTechnologyChangeFailed(@ImsRegistrationTech int imsRadioTech,
             ImsReasonInfo info) {
         mCallbacks.broadcast((c) -> {
@@ -233,6 +247,11 @@
         });
     }
 
+    /**
+     * The this device's subscriber associated {@link Uri}s have changed, which are used to filter
+     * out this device's {@link Uri}s during conference calling.
+     * @param uris
+     */
     public final void onSubscriberAssociatedUriChanged(Uri[] uris) {
         mCallbacks.broadcast((c) -> {
             try {
@@ -264,6 +283,11 @@
         }
     }
 
+    /**
+     * @return the current registration connection type. Valid values are
+     * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}
+     * @hide
+     */
     @VisibleForTesting
     public final @ImsRegistrationTech int getConnectionType() {
         synchronized (mLock) {
diff --git a/telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
similarity index 97%
rename from telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java
rename to telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
index 57df526..bf89533 100644
--- a/telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
@@ -14,17 +14,16 @@
  * limitations under the License
  */
 
-package android.telephony.ims.internal.stub;
+package android.telephony.ims.stub;
 
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
 import android.os.RemoteException;
 import android.telephony.SmsManager;
 import android.telephony.SmsMessage;
+import android.telephony.ims.aidl.IImsSmsListener;
 import android.util.Log;
 
-import com.android.ims.internal.IImsSmsListener;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -37,7 +36,7 @@
  * @hide
  */
 @SystemApi
-public class SmsImplBase {
+public class ImsSmsImplBase {
     private static final String LOG_TAG = "SmsImplBase";
 
     /** @hide */
@@ -158,7 +157,7 @@
      * @param token token provided in {@link #onSmsReceived(int, String, byte[])}
      * @param result result of delivering the message. Valid values are:
      *  {@link #DELIVER_STATUS_OK},
-     *  {@link #DELIVER_STATUS_OK}
+     *  {@link #DELIVER_STATUS_ERROR}
      * @param messageRef the message reference
      */
     public void acknowledgeSms(int token, @DeliverStatusResult int messageRef, int result) {
@@ -303,9 +302,9 @@
     }
 
     /**
-     * Called when SmsImpl has been initialized and communication with the framework is set up.
+     * Called when ImsSmsImpl has been initialized and communication with the framework is set up.
      * Any attempt by this class to access the framework before this method is called will return
-     * with an {@link RuntimeException}.
+     * with a {@link RuntimeException}.
      */
     public void onReady() {
         // Base Implementation - Should be overridden
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
index 054a8b2..fcd7faf 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
@@ -16,177 +16,332 @@
 
 package android.telephony.ims.stub;
 
+import android.annotation.SystemApi;
 import android.os.Bundle;
 import android.os.RemoteException;
+import android.telephony.ims.ImsUtListener;
 
 import com.android.ims.internal.IImsUt;
 import com.android.ims.internal.IImsUtListener;
 
 /**
- * Base implementation of ImsUt, which implements stub versions of the methods
- * in the IImsUt AIDL. Override the methods that your implementation of ImsUt supports.
- *
- * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
- * will break other implementations of ImsUt maintained by other ImsServices.
- *
- * Provides the Ut interface interworking to get/set the supplementary service configuration.
+ * Base implementation of IMS UT interface, which implements stubs. Override these methods to
+ * implement functionality.
  *
  * @hide
  */
+// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+// will break other implementations of ImsUt maintained by other ImsServices.
+@SystemApi
+public class ImsUtImplBase {
 
-public class ImsUtImplBase extends IImsUt.Stub {
+    private IImsUt.Stub mServiceImpl = new IImsUt.Stub() {
+        @Override
+        public void close() throws RemoteException {
+            ImsUtImplBase.this.close();
+        }
+
+        @Override
+        public int queryCallBarring(int cbType) throws RemoteException {
+            return ImsUtImplBase.this.queryCallBarring(cbType);
+        }
+
+        @Override
+        public int queryCallForward(int condition, String number) throws RemoteException {
+            return ImsUtImplBase.this.queryCallForward(condition, number);
+        }
+
+        @Override
+        public int queryCallWaiting() throws RemoteException {
+            return ImsUtImplBase.this.queryCallWaiting();
+        }
+
+        @Override
+        public int queryCLIR() throws RemoteException {
+            return ImsUtImplBase.this.queryCLIR();
+        }
+
+        @Override
+        public int queryCLIP() throws RemoteException {
+            return ImsUtImplBase.this.queryCLIP();
+        }
+
+        @Override
+        public int queryCOLR() throws RemoteException {
+            return ImsUtImplBase.this.queryCOLR();
+        }
+
+        @Override
+        public int queryCOLP() throws RemoteException {
+            return ImsUtImplBase.this.queryCOLP();
+        }
+
+        @Override
+        public int transact(Bundle ssInfo) throws RemoteException {
+            return ImsUtImplBase.this.transact(ssInfo);
+        }
+
+        @Override
+        public int updateCallBarring(int cbType, int action, String[] barrList) throws
+                RemoteException {
+            return ImsUtImplBase.this.updateCallBarring(cbType, action, barrList);
+        }
+
+        @Override
+        public int updateCallForward(int action, int condition, String number, int serviceClass,
+                int timeSeconds) throws RemoteException {
+            return ImsUtImplBase.this.updateCallForward(action, condition, number, serviceClass,
+                    timeSeconds);
+        }
+
+        @Override
+        public int updateCallWaiting(boolean enable, int serviceClass) throws RemoteException {
+            return ImsUtImplBase.this.updateCallWaiting(enable, serviceClass);
+        }
+
+        @Override
+        public int updateCLIR(int clirMode) throws RemoteException {
+            return ImsUtImplBase.this.updateCLIR(clirMode);
+        }
+
+        @Override
+        public int updateCLIP(boolean enable) throws RemoteException {
+            return ImsUtImplBase.this.updateCLIP(enable);
+        }
+
+        @Override
+        public int updateCOLR(int presentation) throws RemoteException {
+            return ImsUtImplBase.this.updateCOLR(presentation);
+        }
+
+        @Override
+        public int updateCOLP(boolean enable) throws RemoteException {
+            return ImsUtImplBase.this.updateCOLP(enable);
+        }
+
+        @Override
+        public void setListener(IImsUtListener listener) throws RemoteException {
+            ImsUtImplBase.this.setListener(new ImsUtListener(listener));
+        }
+
+        @Override
+        public int queryCallBarringForServiceClass(int cbType, int serviceClass)
+                throws RemoteException {
+            return ImsUtImplBase.this.queryCallBarringForServiceClass(cbType, serviceClass);
+        }
+
+        @Override
+        public int updateCallBarringForServiceClass(int cbType, int action,
+                String[] barrList, int serviceClass) throws RemoteException {
+            return ImsUtImplBase.this.updateCallBarringForServiceClass(
+                    cbType, action, barrList, serviceClass);
+        }
+    };
 
     /**
-     * Closes the object. This object is not usable after being closed.
+     * Called when the framework no longer needs to interact with the IMS UT implementation any
+     * longer.
      */
-    @Override
-    public void close() throws RemoteException {
+    public void close() {
 
     }
 
     /**
-     * Retrieves the configuration of the call barring.
+     * Retrieves the call barring configuration.
+     * @param cbType
      */
-    @Override
-    public int queryCallBarring(int cbType) throws RemoteException {
+    public int queryCallBarring(int cbType) {
         return -1;
     }
 
     /**
      * Retrieves the configuration of the call barring for specified service class.
      */
-    @Override
-    public int queryCallBarringForServiceClass(int cbType, int serviceClass)
-            throws RemoteException {
+    public int queryCallBarringForServiceClass(int cbType, int serviceClass) {
         return -1;
     }
 
     /**
      * Retrieves the configuration of the call forward.
      */
-    @Override
-    public int queryCallForward(int condition, String number) throws RemoteException {
+    public int queryCallForward(int condition, String number) {
         return -1;
     }
 
     /**
      * Retrieves the configuration of the call waiting.
      */
-    @Override
-    public int queryCallWaiting() throws RemoteException {
+    public int queryCallWaiting() {
         return -1;
     }
 
     /**
      * Retrieves the default CLIR setting.
+     * @hide
      */
-    @Override
-    public int queryCLIR() throws RemoteException {
+    public int queryCLIR() {
+        return queryClir();
+    }
+
+    /**
+     * Retrieves the CLIP call setting.
+     * @hide
+     */
+    public int queryCLIP() {
+        return queryClip();
+    }
+
+    /**
+     * Retrieves the COLR call setting.
+     * @hide
+     */
+    public int queryCOLR() {
+        return queryColr();
+    }
+
+    /**
+     * Retrieves the COLP call setting.
+     * @hide
+     */
+    public int queryCOLP() {
+        return queryColp();
+    }
+
+    /**
+     * Retrieves the default CLIR setting.
+     */
+    public int queryClir() {
         return -1;
     }
 
     /**
      * Retrieves the CLIP call setting.
      */
-    @Override
-    public int queryCLIP() throws RemoteException {
+    public int queryClip() {
         return -1;
     }
 
     /**
      * Retrieves the COLR call setting.
      */
-    @Override
-    public int queryCOLR() throws RemoteException {
+    public int queryColr() {
         return -1;
     }
 
     /**
      * Retrieves the COLP call setting.
      */
-    @Override
-    public int queryCOLP() throws RemoteException {
+    public int queryColp() {
         return -1;
     }
 
     /**
      * Updates or retrieves the supplementary service configuration.
      */
-    @Override
-    public int transact(Bundle ssInfo) throws RemoteException {
+    public int transact(Bundle ssInfo) {
         return -1;
     }
 
     /**
      * Updates the configuration of the call barring.
      */
-    @Override
-    public int updateCallBarring(int cbType, int action, String[] barrList) throws RemoteException {
+    public int updateCallBarring(int cbType, int action, String[] barrList) {
         return -1;
     }
 
     /**
      * Updates the configuration of the call barring for specified service class.
      */
-    @Override
     public int updateCallBarringForServiceClass(int cbType, int action, String[] barrList,
-            int serviceClass) throws RemoteException {
+            int serviceClass) {
         return -1;
     }
 
     /**
      * Updates the configuration of the call forward.
      */
-    @Override
     public int updateCallForward(int action, int condition, String number, int serviceClass,
-            int timeSeconds) throws RemoteException {
+            int timeSeconds) {
         return 0;
     }
 
     /**
      * Updates the configuration of the call waiting.
      */
-    @Override
-    public int updateCallWaiting(boolean enable, int serviceClass) throws RemoteException {
+    public int updateCallWaiting(boolean enable, int serviceClass) {
         return -1;
     }
 
     /**
      * Updates the configuration of the CLIR supplementary service.
+     * @hide
      */
-    @Override
-    public int updateCLIR(int clirMode) throws RemoteException {
+    public int updateCLIR(int clirMode) {
+        return updateClir(clirMode);
+    }
+
+    /**
+     * Updates the configuration of the CLIP supplementary service.
+     * @hide
+     */
+    public int updateCLIP(boolean enable) {
+        return updateClip(enable);
+    }
+
+    /**
+     * Updates the configuration of the COLR supplementary service.
+     * @hide
+     */
+    public int updateCOLR(int presentation) {
+        return updateColr(presentation);
+    }
+
+    /**
+     * Updates the configuration of the COLP supplementary service.
+     * @hide
+     */
+    public int updateCOLP(boolean enable) {
+        return updateColp(enable);
+    }
+
+    /**
+     * Updates the configuration of the CLIR supplementary service.
+     */
+    public int updateClir(int clirMode) {
         return -1;
     }
 
     /**
      * Updates the configuration of the CLIP supplementary service.
      */
-    @Override
-    public int updateCLIP(boolean enable) throws RemoteException {
+    public int updateClip(boolean enable) {
         return -1;
     }
 
     /**
      * Updates the configuration of the COLR supplementary service.
      */
-    @Override
-    public int updateCOLR(int presentation) throws RemoteException {
+    public int updateColr(int presentation) {
         return -1;
     }
 
     /**
      * Updates the configuration of the COLP supplementary service.
      */
-    @Override
-    public int updateCOLP(boolean enable) throws RemoteException {
+    public int updateColp(boolean enable) {
         return -1;
     }
 
     /**
      * Sets the listener.
      */
-    @Override
-    public void setListener(IImsUtListener listener) throws RemoteException {
+    public void setListener(ImsUtListener listener) {
+    }
+
+    /**
+     * @hide
+     */
+    public IImsUt getInterface() {
+        return mServiceImpl;
     }
 }
diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java
index cf4c47b..421b015 100644
--- a/telephony/java/com/android/ims/ImsConfig.java
+++ b/telephony/java/com/android/ims/ImsConfig.java
@@ -19,8 +19,9 @@
 import android.content.Context;
 import android.os.RemoteException;
 import android.telephony.Rlog;
-
-import com.android.ims.internal.IImsConfig;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.stub.ImsConfigImplBase;
 
 /**
  * Provides APIs to get/set the IMS service feature/capability/parameters.
@@ -46,7 +47,7 @@
 
     /**
      * Broadcast action: the configuration was changed
-     *
+     * @deprecated Use {@link ImsConfig#addConfigCallback(ImsConfigImplBase.Callback)} instead.
      * @hide
      */
     public static final String ACTION_IMS_CONFIG_CHANGED =
@@ -70,6 +71,8 @@
 
     /**
     * Defines IMS service/capability feature constants.
+    * @deprecated Use
+     * {@link android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability} instead.
     */
     public static class FeatureConstants {
         public static final int FEATURE_TYPE_UNKNOWN = -1;
@@ -539,162 +542,164 @@
     }
 
     public ImsConfig(IImsConfig iconfig, Context context) {
-        if (DBG) Rlog.d(TAG, "ImsConfig creates");
+        if (DBG) Rlog.d(TAG, "ImsConfig created");
         miConfig = iconfig;
         mContext = context;
     }
 
     /**
-     * Gets the provisioned value for IMS service/capabilities parameters used by IMS stack.
-     * This function should not be called from the mainthread as it could block the
-     * mainthread.
+     * @deprecated see {@link #getInt(int)} instead.
+     */
+    public int getProvisionedValue(int item) throws ImsException {
+        return getConfigInt(item);
+    }
+
+    /**
+     * Gets the configuration value for IMS service/capabilities parameters used by IMS stack.
      *
      * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
      * @return the value in Integer format.
-     *
-     * @throws ImsException if calling the IMS service results in an error.
+     * @throws ImsException if the ImsService is unavailable.
      */
-    public int getProvisionedValue(int item) throws ImsException {
+    public int getConfigInt(int item) throws ImsException {
         int ret = 0;
         try {
-            ret = miConfig.getProvisionedValue(item);
+            ret = miConfig.getConfigInt(item);
         }  catch (RemoteException e) {
-            throw new ImsException("getValue()", e,
+            throw new ImsException("getInt()", e,
                     ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
         }
-        if (DBG) Rlog.d(TAG, "getProvisionedValue(): item = " + item + ", ret =" + ret);
+        if (DBG) Rlog.d(TAG, "getInt(): item = " + item + ", ret =" + ret);
 
         return ret;
     }
 
     /**
-     * Gets the provisioned value for IMS service/capabilities parameters used by IMS stack.
-     * This function should not be called from the mainthread as it could block the
-     * mainthread.
+     * @deprecated see {@link #getConfigString(int)} instead
+     */
+    public String getProvisionedStringValue(int item) throws ImsException {
+        return getConfigString(item);
+    }
+
+    /**
+     * Gets the configuration value for IMS service/capabilities parameters used by IMS stack.
      *
      * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
      * @return value in String format.
      *
-     * @throws ImsException if calling the IMS service results in an error.
+     * @throws ImsException if the ImsService is unavailable.
      */
-    public String getProvisionedStringValue(int item) throws ImsException {
+    public String getConfigString(int item) throws ImsException {
         String ret = "Unknown";
         try {
-            ret = miConfig.getProvisionedStringValue(item);
+            ret = miConfig.getConfigString(item);
         }  catch (RemoteException e) {
-            throw new ImsException("getProvisionedStringValue()", e,
+            throw new ImsException("getConfigString()", e,
                     ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
         }
-        if (DBG) Rlog.d(TAG, "getProvisionedStringValue(): item = " + item + ", ret =" + ret);
+        if (DBG) Rlog.d(TAG, "getConfigString(): item = " + item + ", ret =" + ret);
 
         return ret;
     }
 
     /**
-     * Sets the value for IMS service/capabilities parameters by
-     * the operator device management entity.
-     * This function should not be called from main thread as it could block
-     * mainthread.
+     * @deprecated see {@link #setConfig(int, int)} instead.
+     */
+    public int setProvisionedValue(int item, int value) throws ImsException {
+        return setConfig(item, value);
+    }
+
+    /**
+     * @deprecated see {@link #setConfig(int, String)} instead.
+     */
+    public int setProvisionedStringValue(int item, String value) throws ImsException {
+        return setConfig(item, value);
+    }
+
+    /**
+     * Sets the value for ImsService configuration item.
      *
      * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
      * @param value in Integer format.
      * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants
      *
-     * @throws ImsException if calling the IMS service results in an error.
+     * @throws ImsException if the ImsService is unavailable.
      */
-    public int setProvisionedValue(int item, int value)
-            throws ImsException {
+    public int setConfig(int item, int value) throws ImsException {
         int ret = OperationStatusConstants.UNKNOWN;
         if (DBG) {
-            Rlog.d(TAG, "setProvisionedValue(): item = " + item +
+            Rlog.d(TAG, "setConfig(): item = " + item +
                     "value = " + value);
         }
         try {
-            ret = miConfig.setProvisionedValue(item, value);
+            ret = miConfig.setConfigInt(item, value);
         }  catch (RemoteException e) {
-            throw new ImsException("setProvisionedValue()", e,
+            throw new ImsException("setConfig()", e,
                     ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
         }
         if (DBG) {
-            Rlog.d(TAG, "setProvisionedValue(): item = " + item +
+            Rlog.d(TAG, "setConfig(): item = " + item +
+                    " value = " + value + " ret = " + ret);
+        }
+        return ret;
+
+    }
+
+    /**
+     * Sets the value for ImsService configuration item.
+     *
+     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @param value in Integer format.
+     * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants
+     *
+     * @throws ImsException if the ImsService is unavailable.
+     */
+    public int setConfig(int item, String value) throws ImsException {
+        int ret = OperationStatusConstants.UNKNOWN;
+        if (DBG) {
+            Rlog.d(TAG, "setConfig(): item = " + item +
+                    "value = " + value);
+        }
+        try {
+            ret = miConfig.setConfigString(item, value);
+        }  catch (RemoteException e) {
+            throw new ImsException("setConfig()", e,
+                    ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
+        }
+        if (DBG) {
+            Rlog.d(TAG, "setConfig(): item = " + item +
                     " value = " + value + " ret = " + ret);
         }
         return ret;
     }
 
     /**
-     * Sets the value for IMS service/capabilities parameters by
-     * the operator device management entity.
-     * This function should not be called from main thread as it could block
-     * mainthread.
+     * Adds a {@link ImsConfigImplBase.Callback} to the ImsService to notify when a Configuration
+     * item has changed.
      *
-     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
-     * @param value in String format.
-     * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants
-     *
-     * @throws ImsException if calling the IMS service results in an error.
+     * Make sure to call {@link #removeConfigCallback(ImsConfigImplBase.Callback)} when finished
+     * using this callback.
      */
-    public int setProvisionedStringValue(int item, String value)
-            throws ImsException {
-        int ret = OperationStatusConstants.UNKNOWN;
+    public void addConfigCallback(ImsConfigImplBase.Callback callback) throws ImsException {
+        if (DBG) Rlog.d(TAG, "addConfigCallback: " + callback);
         try {
-            ret = miConfig.setProvisionedStringValue(item, value);
+            miConfig.addImsConfigCallback(callback);
         }  catch (RemoteException e) {
-            throw new ImsException("setProvisionedStringValue()", e,
-                    ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
-        }
-        if (DBG) {
-            Rlog.d(TAG, "setProvisionedStringValue(): item = " + item +
-                    ", value =" + value);
-        }
-        return ret;
-    }
-
-    /**
-     * Gets the value for IMS feature item for specified network type.
-     *
-     * @param feature, defined as in FeatureConstants.
-     * @param network, defined as in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
-     * @param listener, provided to be notified for the feature on/off status.
-     * @return void
-     *
-     * @throws ImsException if calling the IMS service results in an error.
-     */
-    public void getFeatureValue(int feature, int network,
-            ImsConfigListener listener) throws ImsException {
-        if (DBG) {
-            Rlog.d(TAG, "getFeatureValue: feature = " + feature + ", network =" + network +
-                    ", listener =" + listener);
-        }
-        try {
-            miConfig.getFeatureValue(feature, network, listener);
-        } catch (RemoteException e) {
-            throw new ImsException("getFeatureValue()", e,
+            throw new ImsException("addConfigCallback()", e,
                     ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
         }
     }
 
     /**
-     * Sets the value for IMS feature item for specified network type.
-     *
-     * @param feature, as defined in FeatureConstants.
-     * @param network, as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
-     * @param value, as defined in FeatureValueConstants.
-     * @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.
+     * Removes a {@link ImsConfigImplBase.Callback} from the ImsService that was previously added
+     * by {@link #addConfigCallback(ImsConfigImplBase.Callback)}.
      */
-    public void setFeatureValue(int feature, int network, int value,
-            ImsConfigListener listener) throws ImsException {
-        if (DBG) {
-            Rlog.d(TAG, "setFeatureValue: feature = " + feature + ", network =" + network +
-                    ", value =" + value + ", listener =" + listener);
-        }
+    public void removeConfigCallback(ImsConfigImplBase.Callback callback) throws ImsException {
+        if (DBG) Rlog.d(TAG, "removeConfigCallback: " + callback);
         try {
-            miConfig.setFeatureValue(feature, network, value, listener);
-        } catch (RemoteException e) {
-            throw new ImsException("setFeatureValue()", e,
+            miConfig.removeImsConfigCallback(callback);
+        }  catch (RemoteException e) {
+            throw new ImsException("removeConfigCallback()", e,
                     ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
         }
     }
diff --git a/telephony/java/com/android/ims/ImsException.java b/telephony/java/com/android/ims/ImsException.java
index 0e8bad7..f35e886 100644
--- a/telephony/java/com/android/ims/ImsException.java
+++ b/telephony/java/com/android/ims/ImsException.java
@@ -16,6 +16,8 @@
 
 package com.android.ims;
 
+import android.telephony.ims.ImsReasonInfo;
+
 /**
  * This class defines a general IMS-related exception.
  *
diff --git a/telephony/java/com/android/ims/ImsUtInterface.java b/telephony/java/com/android/ims/ImsUtInterface.java
index 14c184a..c9d4405 100644
--- a/telephony/java/com/android/ims/ImsUtInterface.java
+++ b/telephony/java/com/android/ims/ImsUtInterface.java
@@ -18,6 +18,8 @@
 
 import android.os.Handler;
 import android.os.Message;
+import android.telephony.ims.ImsCallForwardInfo;
+import android.telephony.ims.ImsSsInfo;
 
 /**
  * Provides APIs for the supplementary service settings using IMS (Ut interface).
diff --git a/telephony/java/com/android/ims/internal/IImsCallSession.aidl b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
index c6fc5e5..203e6cf 100644
--- a/telephony/java/com/android/ims/internal/IImsCallSession.aidl
+++ b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
@@ -17,9 +17,10 @@
 package com.android.ims.internal;
 
 import android.os.Message;
-import com.android.ims.ImsCallProfile;
-import com.android.ims.ImsStreamMediaProfile;
-import com.android.ims.internal.IImsCallSessionListener;
+import android.telephony.ims.aidl.IImsCallSessionListener;
+
+import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsStreamMediaProfile;
 import com.android.ims.internal.IImsVideoCallProvider;
 
 /**
diff --git a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
index 748092d..a8e8b7dd 100644
--- a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
@@ -16,12 +16,12 @@
 
 package com.android.ims.internal;
 
-import com.android.ims.ImsStreamMediaProfile;
-import com.android.ims.ImsCallProfile;
-import com.android.ims.ImsReasonInfo;
-import com.android.ims.ImsConferenceState;
+import android.telephony.ims.ImsStreamMediaProfile;
+import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsConferenceState;
 import com.android.ims.internal.IImsCallSession;
-import com.android.ims.ImsSuppServiceNotification;
+import android.telephony.ims.ImsSuppServiceNotification;
 
 /**
  * A listener type for receiving notification on IMS call session events.
diff --git a/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl b/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl
index 1621967..b3d8139 100644
--- a/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl
@@ -16,7 +16,7 @@
 
 package com.android.ims.internal;
 
-import com.android.ims.ImsExternalCallState;
+import android.telephony.ims.ImsExternalCallState;
 
 /**
  * A listener type for receiving notifications about DEP through IMS
diff --git a/telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl b/telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl
index 41b1042..b83b130 100644
--- a/telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl
+++ b/telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl
@@ -17,9 +17,9 @@
 package com.android.ims.internal;
 
 /**
-*  Interface from ImsFeature in the ImsService to ImsServiceController.
+ * Interface from ImsFeature in the ImsService to ImsServiceController.
  * {@hide}
  */
 oneway interface IImsFeatureStatusCallback {
     void notifyImsFeatureStatus(int featureStatus);
-}
\ No newline at end of file
+}
diff --git a/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl b/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl
index 10c7f3e..5151192 100644
--- a/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl
+++ b/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl
@@ -18,14 +18,12 @@
 
 import android.app.PendingIntent;
 
-import com.android.ims.ImsCallProfile;
+import android.telephony.ims.ImsCallProfile;
 import com.android.ims.internal.IImsCallSession;
-import com.android.ims.internal.IImsCallSessionListener;
 import com.android.ims.internal.IImsConfig;
 import com.android.ims.internal.IImsEcbm;
 import com.android.ims.internal.IImsMultiEndpoint;
 import com.android.ims.internal.IImsRegistrationListener;
-import com.android.ims.internal.IImsSmsListener;
 import com.android.ims.internal.IImsUt;
 
 import android.os.Message;
@@ -44,8 +42,7 @@
     void addRegistrationListener(in IImsRegistrationListener listener);
     void removeRegistrationListener(in IImsRegistrationListener listener);
     ImsCallProfile createCallProfile(int sessionId, int callSessionType, int callType);
-    IImsCallSession createCallSession(int sessionId, in ImsCallProfile profile,
-            IImsCallSessionListener listener);
+    IImsCallSession createCallSession(int sessionId, in ImsCallProfile profile);
     IImsCallSession getPendingCallSession(int sessionId, String callId);
     IImsUt getUtInterface();
     IImsConfig getConfigInterface();
@@ -54,12 +51,4 @@
     IImsEcbm getEcbmInterface();
     void setUiTTYMode(int uiTtyMode, in Message onComplete);
     IImsMultiEndpoint getMultiEndpointInterface();
-    // SMS APIs
-    void setSmsListener(IImsSmsListener l);
-    oneway void sendSms(in int token, int messageRef, String format, String smsc, boolean retry,
-            in byte[] pdu);
-    oneway void acknowledgeSms(int token, int messageRef, int result);
-    oneway void acknowledgeSmsReport(int token, int messageRef, int result);
-    String getSmsFormat();
-    oneway void onSmsReady();
 }
diff --git a/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
index 15f8726..2212109 100644
--- a/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
@@ -16,7 +16,7 @@
 
 package com.android.ims.internal;
 
-import com.android.ims.ImsReasonInfo;
+import android.telephony.ims.ImsReasonInfo;
 
 import android.net.Uri;
 
diff --git a/telephony/java/com/android/ims/internal/IImsService.aidl b/telephony/java/com/android/ims/internal/IImsService.aidl
index 406d22d..c3cc6fb 100644
--- a/telephony/java/com/android/ims/internal/IImsService.aidl
+++ b/telephony/java/com/android/ims/internal/IImsService.aidl
@@ -18,7 +18,7 @@
 
 import android.app.PendingIntent;
 
-import com.android.ims.ImsCallProfile;
+import android.telephony.ims.ImsCallProfile;
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsCallSessionListener;
 import com.android.ims.internal.IImsConfig;
diff --git a/telephony/java/com/android/ims/internal/IImsServiceController.aidl b/telephony/java/com/android/ims/internal/IImsServiceController.aidl
index 7ac25ac..857089f 100644
--- a/telephony/java/com/android/ims/internal/IImsServiceController.aidl
+++ b/telephony/java/com/android/ims/internal/IImsServiceController.aidl
@@ -18,7 +18,6 @@
 
 import com.android.ims.internal.IImsFeatureStatusCallback;
 import com.android.ims.internal.IImsMMTelFeature;
-import com.android.ims.internal.IImsRegistration;
 import com.android.ims.internal.IImsRcsFeature;
 
 /**
@@ -30,5 +29,4 @@
     IImsMMTelFeature createMMTelFeature(int slotId, in IImsFeatureStatusCallback c);
     IImsRcsFeature createRcsFeature(int slotId, in IImsFeatureStatusCallback c);
     void removeImsFeature(int slotId, int featureType, in IImsFeatureStatusCallback c);
-    IImsRegistration getRegistration(int slotId);
 }
diff --git a/telephony/java/com/android/ims/internal/IImsUtListener.aidl b/telephony/java/com/android/ims/internal/IImsUtListener.aidl
index 1bc0369..a603cd3 100644
--- a/telephony/java/com/android/ims/internal/IImsUtListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsUtListener.aidl
@@ -18,11 +18,11 @@
 
 import android.os.Bundle;
 
-import com.android.ims.ImsCallForwardInfo;
-import com.android.ims.ImsSsData;
-import com.android.ims.ImsSsInfo;
+import android.telephony.ims.ImsCallForwardInfo;
+import android.telephony.ims.ImsSsInfo;
 import com.android.ims.internal.IImsUt;
-import com.android.ims.ImsReasonInfo;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsSsData;
 
 /**
  * {@hide}
diff --git a/telephony/java/com/android/internal/telephony/ExponentialBackoff.java b/telephony/java/com/android/internal/telephony/ExponentialBackoff.java
index 80958c0..f323a0c 100644
--- a/telephony/java/com/android/internal/telephony/ExponentialBackoff.java
+++ b/telephony/java/com/android/internal/telephony/ExponentialBackoff.java
@@ -20,6 +20,8 @@
 import android.os.Handler;
 import android.os.Looper;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 /** The implementation of exponential backoff with jitter applied. */
 public class ExponentialBackoff {
     private int mRetryCounter;
@@ -27,8 +29,31 @@
     private long mMaximumDelayMs;
     private long mCurrentDelayMs;
     private int mMultiplier;
-    private Runnable mRunnable;
-    private Handler mHandler;
+    private final Runnable mRunnable;
+    private final Handler mHandler;
+
+    /**
+     * Implementation of Handler methods, Adapter for testing (can't spy on final methods).
+     */
+    private HandlerAdapter mHandlerAdapter = new HandlerAdapter() {
+        @Override
+        public boolean postDelayed(Runnable runnable, long delayMillis) {
+            return mHandler.postDelayed(runnable, delayMillis);
+        }
+
+        @Override
+        public void removeCallbacks(Runnable runnable) {
+            mHandler.removeCallbacks(runnable);
+        }
+    };
+
+    /**
+     * Need to spy final methods for testing.
+     */
+    public interface HandlerAdapter {
+        boolean postDelayed(Runnable runnable, long delayMillis);
+        void removeCallbacks(Runnable runnable);
+    }
 
     public ExponentialBackoff(
             long initialDelayMs,
@@ -57,14 +82,14 @@
     public void start() {
         mRetryCounter = 0;
         mCurrentDelayMs = mStartDelayMs;
-        mHandler.removeCallbacks(mRunnable);
-        mHandler.postDelayed(mRunnable, mCurrentDelayMs);
+        mHandlerAdapter.removeCallbacks(mRunnable);
+        mHandlerAdapter.postDelayed(mRunnable, mCurrentDelayMs);
     }
 
     /** Stops the backoff, all pending messages will be removed from the message queue. */
     public void stop() {
         mRetryCounter = 0;
-        mHandler.removeCallbacks(mRunnable);
+        mHandlerAdapter.removeCallbacks(mRunnable);
     }
 
     /** Should call when the retry action has failed and we want to retry after a longer delay. */
@@ -73,12 +98,17 @@
         long temp = Math.min(
                 mMaximumDelayMs, (long) (mStartDelayMs * Math.pow(mMultiplier, mRetryCounter)));
         mCurrentDelayMs = (long) (((1 + Math.random()) / 2) * temp);
-        mHandler.removeCallbacks(mRunnable);
-        mHandler.postDelayed(mRunnable, mCurrentDelayMs);
+        mHandlerAdapter.removeCallbacks(mRunnable);
+        mHandlerAdapter.postDelayed(mRunnable, mCurrentDelayMs);
     }
 
     /** Returns the delay for the most recently posted message. */
     public long getCurrentDelay() {
         return mCurrentDelayMs;
     }
+
+    @VisibleForTesting
+    public void setHandlerAdapter(HandlerAdapter a) {
+        mHandlerAdapter  = a;
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 797805b..2b4c059 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -38,9 +38,10 @@
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyHistogram;
 import android.telephony.VisualVoicemailSmsFilterSettings;
-import com.android.ims.internal.IImsMMTelFeature;
-import com.android.ims.internal.IImsRcsFeature;
-import com.android.ims.internal.IImsRegistration;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsMmTelFeature;
+import android.telephony.ims.aidl.IImsRcsFeature;
+import android.telephony.ims.aidl.IImsRegistration;
 import com.android.ims.internal.IImsServiceFeatureCallback;
 import com.android.internal.telephony.CellNetworkScanResult;
 import com.android.internal.telephony.OperatorInfo;
@@ -788,20 +789,21 @@
     int getTetherApnRequired();
 
     /**
-     *  Get IImsMMTelFeature binder from ImsResolver that corresponds to the subId and MMTel feature
-     *  as well as registering the MMTelFeature for callbacks using the IImsServiceFeatureCallback
-     *  interface.
-     */
-    IImsMMTelFeature getMMTelFeatureAndListen(int slotId, in IImsServiceFeatureCallback callback);
+    * Enables framework IMS and triggers IMS Registration.
+    */
+    void enableIms(int slotId);
 
     /**
-     *  Get IImsMMTelFeature binder from ImsResolver that corresponds to the subId and MMTel feature
-     *  as well as registering the MMTelFeature for callbacks using the IImsServiceFeatureCallback
+    * Disables framework IMS and triggers IMS deregistration.
+    */
+    void disableIms(int slotId);
+
+    /**
+     *  Get IImsMmTelFeature binder from ImsResolver that corresponds to the subId and MMTel feature
+     *  as well as registering the MmTelFeature for callbacks using the IImsServiceFeatureCallback
      *  interface.
-     *  Used for emergency calling only.
      */
-    IImsMMTelFeature getEmergencyMMTelFeatureAndListen(int slotId,
-            in IImsServiceFeatureCallback callback);
+    IImsMmTelFeature getMmTelFeatureAndListen(int slotId, in IImsServiceFeatureCallback callback);
 
     /**
      *  Get IImsRcsFeature binder from ImsResolver that corresponds to the subId and RCS feature
@@ -816,6 +818,11 @@
     IImsRegistration getImsRegistration(int slotId, int feature);
 
     /**
+    * Returns the IImsConfig associated with the slot and feature specified.
+    */
+    IImsConfig getImsConfig(int slotId, int feature);
+
+    /**
      * Set the network selection mode to automatic.
      *
      * @param subId the id of the subscription to update.