Misc Telecomm API changes

The CL contains the following Telecomm API changes:
  - move CallFeatures into CallCapabilities
  - add Connection.setHandle(URI, CallPropertyPresentation)
  - add Connection.setCallerDisplayName(String,
    CallPropertyPresentation)
  - add Connection.swapWithBackground: this is used to swap a
    CDMA call with its background call
  - add StatusHints.getExtras: this is used to display
    additional status info such as long distance rates
This CL also includes InCallServcie, and RemoteConnection
plumbing for the above.

Change-Id: Iaffe0b84cea6003f2a9b9d8b30676743d2b236d4
diff --git a/api/current.txt b/api/current.txt
index f09291d..bfe380c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -27583,7 +27583,7 @@
   public final class CallCapabilities {
     method public static java.lang.String toString(int);
     field public static final int ADD_CALL = 16; // 0x10
-    field public static final int ALL = 255; // 0xff
+    field public static final int ALL = 3327; // 0xcff
     field public static final int GENERIC_CONFERENCE = 128; // 0x80
     field public static final int HOLD = 1; // 0x1
     field public static final int MERGE_CALLS = 4; // 0x4
@@ -27593,21 +27593,16 @@
     field public static final int SUPPORTS_VT_REMOTE = 512; // 0x200
     field public static final int SUPPORT_HOLD = 2; // 0x2
     field public static final int SWAP_CALLS = 8; // 0x8
+    field public static final int VoLTE = 1024; // 0x400
+    field public static final int VoWIFI = 2048; // 0x800
   }
 
-  public final class CallFeatures {
-    field public static final int NONE = 0; // 0x0
-    field public static final int VoLTE = 1; // 0x1
-    field public static final int VoWIFI = 2; // 0x2
-  }
-
-  public final class CallNumberPresentation extends java.lang.Enum {
-    method public static android.telecomm.CallNumberPresentation valueOf(java.lang.String);
-    method public static final android.telecomm.CallNumberPresentation[] values();
-    enum_constant public static final android.telecomm.CallNumberPresentation ALLOWED;
-    enum_constant public static final android.telecomm.CallNumberPresentation PAYPHONE;
-    enum_constant public static final android.telecomm.CallNumberPresentation RESTRICTED;
-    enum_constant public static final android.telecomm.CallNumberPresentation UNKNOWN;
+  public class CallPropertyPresentation {
+    ctor public CallPropertyPresentation();
+    field public static final int ALLOWED = 0; // 0x0
+    field public static final int PAYPHONE = 3; // 0x3
+    field public static final int RESTRICTED = 1; // 0x1
+    field public static final int UNKNOWN = 2; // 0x2
   }
 
   public final class CallServiceDescriptor implements android.os.Parcelable {
@@ -27690,9 +27685,11 @@
     method public final android.telecomm.CallAudioState getCallAudioState();
     method public final int getCallCapabilities();
     method public final android.telecomm.CallVideoProvider getCallVideoProvider();
+    method public final java.lang.String getCallerDisplayName();
+    method public final int getCallerDisplayNamePresentation();
     method public final java.util.List<android.telecomm.Connection> getChildConnections();
-    method public final int getFeatures();
     method public final android.net.Uri getHandle();
+    method public final int getHandlePresentation();
     method public final android.telecomm.Connection getParentConnection();
     method public final int getState();
     method public final android.telecomm.StatusHints getStatusHints();
@@ -27711,16 +27708,17 @@
     method protected void onSetAudioState(android.telecomm.CallAudioState);
     method protected void onSetState(int);
     method protected void onStopDtmfTone();
+    method protected void onSwapWithBackgroundCall();
     method protected void onUnhold();
     method public final void setActive();
     method public final void setAudioModeIsVoip(boolean);
     method public final void setCallCapabilities(int);
     method public final void setCallVideoProvider(android.telecomm.CallVideoProvider);
+    method public final void setCallerDisplayName(java.lang.String, int);
     method public final void setDestroyed();
     method public final void setDialing();
     method public final void setDisconnected(int, java.lang.String);
-    method public final void setFeatures(int);
-    method public final void setHandle(android.net.Uri);
+    method public final void setHandle(android.net.Uri, int);
     method public final void setOnHold();
     method public final void setParentConnection(android.telecomm.Connection);
     method public final void setPostDialWait(java.lang.String);
@@ -27741,13 +27739,13 @@
   }
 
   public final class ConnectionRequest implements android.os.Parcelable {
-    ctor public ConnectionRequest(java.lang.String, android.net.Uri, android.os.Bundle, int);
-    ctor public ConnectionRequest(android.telecomm.PhoneAccount, java.lang.String, android.net.Uri, android.os.Bundle, int);
+    ctor public ConnectionRequest(android.telecomm.PhoneAccount, java.lang.String, android.net.Uri, int, android.os.Bundle, int);
     method public int describeContents();
     method public android.telecomm.PhoneAccount getAccount();
     method public java.lang.String getCallId();
     method public android.os.Bundle getExtras();
     method public android.net.Uri getHandle();
+    method public int getHandlePresentation();
     method public int getVideoState();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
@@ -27794,6 +27792,7 @@
     method public void rejectCall(java.lang.String, boolean, java.lang.String);
     method public void setAudioRoute(int);
     method public void stopDtmfTone(java.lang.String);
+    method public void swapWithBackgroundCall(java.lang.String);
     method public void unholdCall(java.lang.String);
   }
 
@@ -27801,15 +27800,17 @@
     method public int describeContents();
     method public android.telecomm.PhoneAccount getAccount();
     method public android.telecomm.RemoteCallVideoProvider getCallVideoProvider() throws android.os.RemoteException;
+    method public java.lang.String getCallerDisplayName();
+    method public int getCallerDisplayNamePresentation();
     method public java.util.List<java.lang.String> getCannedSmsResponses();
     method public int getCapabilities();
     method public long getConnectTimeMillis();
     method public android.telecomm.CallServiceDescriptor getCurrentCallServiceDescriptor();
     method public int getDisconnectCauseCode();
     method public java.lang.String getDisconnectCauseMsg();
-    method public int getFeatures();
     method public android.telecomm.GatewayInfo getGatewayInfo();
     method public android.net.Uri getHandle();
+    method public int getHandlePresentation();
     method public java.lang.String getId();
     method public android.telecomm.CallState getState();
     method public android.telecomm.StatusHints getStatusHints();
@@ -27878,9 +27879,12 @@
     method public void disconnect();
     method public boolean getAudioModeIsVoip();
     method public int getCallCapabilities();
+    method public java.lang.String getCallerDisplayName();
+    method public int getCallerDisplayNamePresentation();
     method public int getDisconnectCause();
     method public java.lang.String getDisconnectMessage();
-    method public int getFeatures();
+    method public android.net.Uri getHandle();
+    method public int getHandlePresentation();
     method public int getState();
     method public android.telecomm.StatusHints getStatusHints();
     method public void hold();
@@ -27890,19 +27894,21 @@
     method public void removeListener(android.telecomm.RemoteConnection.Listener);
     method public void setAudioState(android.telecomm.CallAudioState);
     method public void stopDtmf();
+    method public void swapWithBackgroundCall();
     method public void unhold();
   }
 
   public static abstract interface RemoteConnection.Listener {
+    method public abstract void onAudioModeIsVoipChanged(android.telecomm.RemoteConnection, boolean);
     method public abstract void onCallCapabilitiesChanged(android.telecomm.RemoteConnection, int);
+    method public abstract void onCallerDisplayNameChanged(android.telecomm.RemoteConnection, java.lang.String, int);
     method public abstract void onDestroyed(android.telecomm.RemoteConnection);
     method public abstract void onDisconnected(android.telecomm.RemoteConnection, int, java.lang.String);
-    method public abstract void onFeaturesChanged(android.telecomm.RemoteConnection, int);
+    method public abstract void onHandleChanged(android.telecomm.RemoteConnection, android.net.Uri, int);
     method public abstract void onPostDialWait(android.telecomm.RemoteConnection, java.lang.String);
     method public abstract void onRequestingRingback(android.telecomm.RemoteConnection, boolean);
-    method public abstract void onSetAudioModeIsVoip(android.telecomm.RemoteConnection, boolean);
-    method public abstract void onSetStatusHints(android.telecomm.RemoteConnection, android.telecomm.StatusHints);
     method public abstract void onStateChanged(android.telecomm.RemoteConnection, int);
+    method public abstract void onStatusHintsChanged(android.telecomm.RemoteConnection, android.telecomm.StatusHints);
   }
 
   public abstract interface Response {
@@ -27916,9 +27922,10 @@
   }
 
   public final class StatusHints implements android.os.Parcelable {
-    ctor public StatusHints(android.content.ComponentName, java.lang.String, int);
+    ctor public StatusHints(android.content.ComponentName, java.lang.String, int, android.os.Bundle);
     method public int describeContents();
     method public android.content.ComponentName getComponentName();
+    method public android.os.Bundle getExtras();
     method public android.graphics.drawable.Drawable getIcon(android.content.Context);
     method public int getIconId();
     method public java.lang.String getLabel();
diff --git a/telecomm/java/android/telecomm/CallCapabilities.java b/telecomm/java/android/telecomm/CallCapabilities.java
index 924526e..e64fe80 100644
--- a/telecomm/java/android/telecomm/CallCapabilities.java
+++ b/telecomm/java/android/telecomm/CallCapabilities.java
@@ -48,8 +48,12 @@
     /** Remote device supports video telephony. */
     public static final int SUPPORTS_VT_REMOTE = 0x00000200;
 
+    public static final int VoLTE = 0x00000400;
+
+    public static final int VoWIFI = 0x00000800;
+
     public static final int ALL = HOLD | SUPPORT_HOLD | MERGE_CALLS | SWAP_CALLS | ADD_CALL
-            | RESPOND_VIA_TEXT | MUTE | GENERIC_CONFERENCE;
+            | RESPOND_VIA_TEXT | MUTE | GENERIC_CONFERENCE | VoLTE | VoWIFI;
 
     public static String toString(int capabilities) {
         StringBuilder builder = new StringBuilder();
@@ -84,6 +88,12 @@
         if ((capabilities & SUPPORTS_VT_REMOTE) != 0) {
             builder.append(" SUPPORTS_VT_REMOTE");
         }
+        if ((capabilities & VoLTE) != 0) {
+            builder.append(" VoLTE");
+        }
+        if ((capabilities & VoWIFI) != 0) {
+            builder.append(" VoWIFI");
+        }
         builder.append("]");
         return builder.toString();
     }
diff --git a/telecomm/java/android/telecomm/CallFeatures.java b/telecomm/java/android/telecomm/CallFeatures.java
deleted file mode 100644
index 076d25a..0000000
--- a/telecomm/java/android/telecomm/CallFeatures.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2014 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.telecomm;
-
-/**
- * Defines features of a call.  These features represent properties of a call for which it may be
- * desirable to display an in-call indicator.
- */
-public final class CallFeatures {
-    private CallFeatures() {};
-
-    public static final int NONE = 0x0;
-    public static final int VoLTE = 0x1;
-    public static final int VoWIFI = 0x2;
-}
\ No newline at end of file
diff --git a/telecomm/java/android/telecomm/CallNumberPresentation.java b/telecomm/java/android/telecomm/CallPropertyPresentation.java
similarity index 63%
rename from telecomm/java/android/telecomm/CallNumberPresentation.java
rename to telecomm/java/android/telecomm/CallPropertyPresentation.java
index 6cd22f8..350980c 100644
--- a/telecomm/java/android/telecomm/CallNumberPresentation.java
+++ b/telecomm/java/android/telecomm/CallPropertyPresentation.java
@@ -16,17 +16,17 @@
 
 package android.telecomm;
 
-/** Defines how numbers are displayed in caller id. */
-public enum CallNumberPresentation {
-    /** Number is displayed normally. */
-    ALLOWED,
+/** Defines how numbers and names are displayed in caller id. */
+public class CallPropertyPresentation {
+    /** Property is displayed normally. */
+    public static final int ALLOWED = 0;
 
-    /** Number was blocked. */
-    RESTRICTED,
+    /** Property was blocked. */
+    public static final int RESTRICTED = 1;
 
     /** Presentation was not specified or is unknown. */
-    UNKNOWN,
+    public static final int UNKNOWN = 2;
 
-    /** Number should be displayed as a pay phone. */
-    PAYPHONE
+    /** Property should be displayed as a pay phone. */
+    public static final int PAYPHONE = 3;
 }
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index 05b0062..fb820f0 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -32,62 +32,20 @@
 public abstract class Connection {
 
     /** @hide */
-    public interface Listener {
-        void onStateChanged(Connection c, int state);
-        void onFeaturesChanged(Connection c, int features);
-        void onHandleChanged(Connection c, Uri newHandle);
-        void onSignalChanged(Connection c, Bundle details);
-        void onDisconnected(Connection c, int cause, String message);
-        void onPostDialWait(Connection c, String remaining);
-        void onRequestingRingback(Connection c, boolean ringback);
-        void onDestroyed(Connection c);
-        void onCallCapabilitiesChanged(Connection c, int callCapabilities);
-        void onParentConnectionChanged(Connection c, Connection parent);
-        void onSetCallVideoProvider(Connection c, CallVideoProvider callVideoProvider);
-        void onSetAudioModeIsVoip(Connection c, boolean isVoip);
-        void onSetStatusHints(Connection c, StatusHints statusHints);
-    }
-
-    /** @hide */
-    public static class ListenerBase implements Listener {
-        @Override
+    public abstract static class Listener {
         public void onStateChanged(Connection c, int state) {}
-
-        /** {@inheritDoc} */
-        @Override
-        public void onFeaturesChanged(Connection c, int features) {}
-
-        @Override
-        public void onHandleChanged(Connection c, Uri newHandle) {}
-
-        @Override
+        public void onHandleChanged(Connection c, Uri newHandle, int presentation) {}
+        public void onCallerDisplayNameChanged(
+                Connection c, String callerDisplayName, int presentation) {}
         public void onSignalChanged(Connection c, Bundle details) {}
-
-        @Override
         public void onDisconnected(Connection c, int cause, String message) {}
-
-        @Override
-        public void onDestroyed(Connection c) {}
-
-        @Override
         public void onPostDialWait(Connection c, String remaining) {}
-
-        @Override
         public void onRequestingRingback(Connection c, boolean ringback) {}
-
-        @Override
+        public void onDestroyed(Connection c) {}
         public void onCallCapabilitiesChanged(Connection c, int callCapabilities) {}
-
-        @Override
         public void onParentConnectionChanged(Connection c, Connection parent) {}
-
-        @Override
         public void onSetCallVideoProvider(Connection c, CallVideoProvider callVideoProvider) {}
-
-        @Override
         public void onSetAudioModeIsVoip(Connection c, boolean isVoip) {}
-
-        @Override
         public void onSetStatusHints(Connection c, StatusHints statusHints) {}
     }
 
@@ -106,9 +64,11 @@
     private final List<Connection> mChildConnections = new ArrayList<>();
 
     private int mState = State.NEW;
-    private int mFeatures = CallFeatures.NONE;
     private CallAudioState mCallAudioState;
     private Uri mHandle;
+    private int mHandlePresentation;
+    private String mCallerDisplayName;
+    private int mCallerDisplayNamePresentation;
     private boolean mRequestingRingback = false;
     private int mCallCapabilities;
     private Connection mParentConnection;
@@ -122,21 +82,35 @@
     protected Connection() {}
 
     /**
-     * The handle (e.g., phone number) to which this Connection is currently communicating.
-     *
-     * IMPORTANT: If an incoming connection has a phone number (or other handle) that the user
-     * is not supposed to be able to see (e.g. it is PRESENTATION_RESTRICTED), then a compliant
-     * ConnectionService implementation MUST NOT reveal this phone number and MUST return
-     * {@code null} from this method.
-     *
-     * @return The handle (e.g., phone number) to which this Connection
-     *         is currently communicating.
+     * @return The handle (e.g., phone number) to which this Connection is currently communicating.
      */
     public final Uri getHandle() {
         return mHandle;
     }
 
     /**
+     * @return The {@link CallPropertyPresentation} which controls how the handle is shown.
+     */
+    public final int getHandlePresentation() {
+        return mHandlePresentation;
+    }
+
+    /**
+     * @return The caller display name (CNAP).
+     */
+    public final String getCallerDisplayName() {
+        return mCallerDisplayName;
+    }
+
+    /**
+     * @return The {@link CallPropertyPresentation} which controls how the caller display name is
+     *         shown.
+     */
+    public final int getCallerDisplayNamePresentation() {
+        return mCallerDisplayNamePresentation;
+    }
+
+    /**
      * @return The state of this Connection.
      */
     public final int getState() {
@@ -144,14 +118,6 @@
     }
 
     /**
-     * @return The features of the call.  These are items for which the InCall UI may wish to
-     *         display a visual indicator.
-     */
-    public final int getFeatures() {
-        return mFeatures;
-    }
-
-    /**
      * @return The audio state of the call, describing how its audio is currently
      *         being routed by the system. This is {@code null} if this Connection
      *         does not directly know about its audio state.
@@ -287,31 +253,34 @@
     }
 
     /**
-     * Sets the value of the {@link #getHandle()} property and notifies listeners.
+     * Sets the value of the {@link #getHandle()} property.
      *
      * @param handle The new handle.
+     * @param presentation The {@link CallPropertyPresentation} which controls how the handle is
+     *         shown.
      */
-    public final void setHandle(Uri handle) {
+    public final void setHandle(Uri handle, int presentation) {
         Log.d(this, "setHandle %s", handle);
         mHandle = handle;
+        mHandlePresentation = presentation;
         for (Listener l : mListeners) {
-            l.onHandleChanged(this, handle);
+            l.onHandleChanged(this, handle, presentation);
         }
     }
 
     /**
-     * Set the features applicable to the connection.  These are items for which the InCall UI may
-     * wish to display a visual indicator.
-     * Features are defined in {@link android.telecomm.CallFeatures} and are passed in as a
-     * bit-mask.
+     * Sets the caller display name (CNAP).
      *
-     * @param features The features active.
+     * @param callerDisplayName The new display name.
+     * @param presentation The {@link CallPropertyPresentation} which controls how the name is
+     *         shown.
      */
-    public final void setFeatures(int features) {
-        Log.d(this, "setFeatures %d", features);
-        mFeatures = features;
+    public final void setCallerDisplayName(String callerDisplayName, int presentation) {
+        Log.d(this, "setCallerDisplayName %s", callerDisplayName);
+        mCallerDisplayName = callerDisplayName;
+        mCallerDisplayNamePresentation = presentation;
         for (Listener l : mListeners) {
-            l.onFeaturesChanged(this, mFeatures);
+            l.onCallerDisplayNameChanged(this, callerDisplayName, presentation);
         }
     }
 
@@ -428,8 +397,7 @@
     }
 
     /**
-     * Notifies this Connection and listeners of a change in the current signal levels
-     * for the underlying data transport.
+     * Sets the current signal levels for the underlying data transport.
      *
      * @param details A {@link android.os.Bundle} containing details of the current level.
      */
@@ -464,8 +432,7 @@
     }
 
     /**
-     * Notifies this Connection and listeners that the {@link #getCallAudioState()} property
-     * has a new value.
+     * Notifies this Connection that the {@link #getCallAudioState()} property has a new value.
      *
      * @param state The new call audio state.
      */
@@ -534,6 +501,12 @@
     protected void onPostDialContinue(boolean proceed) {}
 
     /**
+     * Swap this call with a background call. This is used for calls that don't support hold,
+     * e.g. CDMA.
+     */
+    protected void onSwapWithBackgroundCall() {}
+
+    /**
      * TODO(santoscordon): Needs documentation.
      */
     protected void onChildrenChanged(List<Connection> children) {}
diff --git a/telecomm/java/android/telecomm/ConnectionRequest.java b/telecomm/java/android/telecomm/ConnectionRequest.java
index 28fea79..0db9e29 100644
--- a/telecomm/java/android/telecomm/ConnectionRequest.java
+++ b/telecomm/java/android/telecomm/ConnectionRequest.java
@@ -16,8 +16,8 @@
 
 package android.telecomm;
 
-import android.os.Bundle;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -32,20 +32,32 @@
     //         numbers that would satisfy the client's needs, in order of preference
     private final String mCallId;
     private final Uri mHandle;
+    private final int mHandlePresentation;
     private final Bundle mExtras;
     private final PhoneAccount mAccount;
     private final int mVideoState;
 
-    public ConnectionRequest(String callId, Uri handle, Bundle extras, int videoState) {
-        this(null, callId, handle, extras, videoState);
-    }
-
-    public ConnectionRequest(PhoneAccount account, String callId, Uri handle, Bundle extras,
+    /**
+     * @param account The account which should be used to place the call.
+     * @param callId An identifier for this call.
+     * @param handle The handle (e.g., phone number) to which the {@link Connection} is to connect.
+     * @param handlePresentation The {@link CallPropertyPresentation} which controls how the handle
+     *         is shown.
+     * @param extras Application-specific extra data.
+     * @param videoState Determines the video state for the connection.
+     */
+    public ConnectionRequest(
+            PhoneAccount account,
+            String callId,
+            Uri handle,
+            int handlePresentation,
+            Bundle extras,
             int videoState) {
+        mAccount = account;
         mCallId = callId;
         mHandle = handle;
+        mHandlePresentation = handlePresentation;
         mExtras = extras;
-        mAccount = account;
         mVideoState = videoState;
     }
 
@@ -65,6 +77,11 @@
     public Uri getHandle() { return mHandle; }
 
     /**
+     * The {@link CallPropertyPresentation} which controls how the handle is shown.
+     */
+    public int getHandlePresentation() { return mHandlePresentation; }
+
+    /**
      * Application-specific extra data. Used for passing back information from an incoming
      * call {@code Intent}, and for any proprietary extensions arranged between a client
      * and servant {@code ConnectionService} which agree on a vocabulary for such data.
@@ -96,11 +113,15 @@
             new Parcelable.Creator<ConnectionRequest> () {
                 @Override
                 public ConnectionRequest createFromParcel(Parcel source) {
+                    PhoneAccount account = (PhoneAccount) source.readParcelable(
+                            getClass().getClassLoader());
                     String callId = source.readString();
                     Uri handle = (Uri) source.readParcelable(getClass().getClassLoader());
+                    int presentation = source.readInt();
                     Bundle extras = (Bundle) source.readParcelable(getClass().getClassLoader());
                     int videoState = source.readInt();
-                    return new ConnectionRequest(callId, handle, extras, videoState);
+                    return new ConnectionRequest(
+                            account, callId, handle, presentation, extras, videoState);
                 }
 
                 @Override
@@ -119,8 +140,10 @@
 
     @Override
     public void writeToParcel(Parcel destination, int flags) {
+        destination.writeParcelable(mAccount, 0);
         destination.writeString(mCallId);
         destination.writeParcelable(mHandle, 0);
+        destination.writeInt(mHandlePresentation);
         destination.writeParcelable(mExtras, 0);
         destination.writeInt(mVideoState);
     }
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index d0ad0cc..1966081 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -60,8 +60,9 @@
     private static final int MSG_STOP_DTMF_TONE = 12;
     private static final int MSG_CONFERENCE = 13;
     private static final int MSG_SPLIT_FROM_CONFERENCE = 14;
-    private static final int MSG_ON_POST_DIAL_CONTINUE = 15;
-    private static final int MSG_ON_PHONE_ACCOUNT_CLICKED = 16;
+    private static final int MSG_SWAP_WITH_BACKGROUND_CALL = 15;
+    private static final int MSG_ON_POST_DIAL_CONTINUE = 16;
+    private static final int MSG_ON_PHONE_ACCOUNT_CLICKED = 17;
 
     private final Map<String, Connection> mConnectionById = new HashMap<>();
     private final Map<Connection, String> mIdByConnection = new HashMap<>();
@@ -179,6 +180,11 @@
         }
 
         @Override
+        public void swapWithBackgroundCall(String callId) {
+            mHandler.obtainMessage(MSG_SWAP_WITH_BACKGROUND_CALL, callId).sendToTarget();
+        }
+
+        @Override
         public void onPostDialContinue(String callId, boolean proceed) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = callId;
@@ -255,6 +261,9 @@
                 case MSG_SPLIT_FROM_CONFERENCE:
                     splitFromConference((String) msg.obj);
                     break;
+                case MSG_SWAP_WITH_BACKGROUND_CALL:
+                    swapWithBackgroundCall((String) msg.obj);
+                    break;
                 case MSG_ON_POST_DIAL_CONTINUE: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
@@ -302,14 +311,6 @@
             }
         }
 
-        /** {@inheritDoc} */
-        @Override
-        public void onFeaturesChanged(Connection c, int features) {
-            String id = mIdByConnection.get(c);
-            Log.d(this, "Adapter set features %d", features);
-            mAdapter.setFeatures(id, features);
-        }
-
         @Override
         public void onDisconnected(Connection c, int cause, String message) {
             String id = mIdByConnection.get(c);
@@ -318,8 +319,16 @@
         }
 
         @Override
-        public void onHandleChanged(Connection c, Uri newHandle) {
-            // TODO: Unsupported yet
+        public void onHandleChanged(Connection c, Uri handle, int presentation) {
+            String id = mIdByConnection.get(c);
+            mAdapter.setHandle(id, handle, presentation);
+        }
+
+        @Override
+        public void onCallerDisplayNameChanged(
+                Connection c, String callerDisplayName, int presentation) {
+            String id = mIdByConnection.get(c);
+            mAdapter.setCallerDisplayName(id, callerDisplayName, presentation);
         }
 
         @Override
@@ -527,6 +536,11 @@
         // TODO(santoscordon): Find existing conference call and invoke split(connection).
     }
 
+    private void swapWithBackgroundCall(String callId) {
+        Log.d(this, "swapWithBackgroundCall(%s)", callId);
+        findConnectionForAction(callId, "swapWithBackgroundCall").onSwapWithBackgroundCall();
+    }
+
     private void onPostDialContinue(String callId, boolean proceed) {
         Log.d(this, "onPostDialContinue(%s)", callId);
         findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed);
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
index f71544b..b90dec3 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
@@ -17,6 +17,7 @@
 package android.telecomm;
 
 import android.content.ComponentName;
+import android.net.Uri;
 import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
 import android.os.RemoteException;
@@ -342,20 +343,20 @@
         }
     }
 
-    /**
-    * Set the features associated with the given call.
-    * Features are defined in {@link android.telecomm.CallFeatures} and are passed in as a
-    * bit-mask.
-    *
-    * @param callId The unique ID of the call to set features for.
-    * @param features The features.
-    */
-    void setFeatures(String callId, int features) {
-        Log.v(this, "setFeatures: %d", features);
+    void setHandle(String callId, Uri handle, int presentation) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setFeatures(callId, features);
-            } catch (RemoteException ignored) {
+                adapter.setHandle(callId, handle, presentation);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    void setCallerDisplayName(String callId, String callerDisplayName, int presentation) {
+        for (IConnectionServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.setCallerDisplayName(callId, callerDisplayName, presentation);
+            } catch (RemoteException e) {
             }
         }
     }
diff --git a/telecomm/java/android/telecomm/InCallAdapter.java b/telecomm/java/android/telecomm/InCallAdapter.java
index aef05fd..d8293a5 100644
--- a/telecomm/java/android/telecomm/InCallAdapter.java
+++ b/telecomm/java/android/telecomm/InCallAdapter.java
@@ -226,4 +226,17 @@
         } catch (RemoteException ignored) {
         }
     }
+
+    /**
+     * Swap this call with a background call. This is used for calls that don't support hold,
+     * e.g. CDMA.
+     *
+     * @param callId The unique ID of the call.
+     */
+    public void swapWithBackgroundCall(String callId) {
+        try {
+            mAdapter.swapWithBackgroundCall(callId);
+        } catch (RemoteException ignored) {
+        }
+    }
 }
diff --git a/telecomm/java/android/telecomm/InCallCall.java b/telecomm/java/android/telecomm/InCallCall.java
index 5396688..7c35020 100644
--- a/telecomm/java/android/telecomm/InCallCall.java
+++ b/telecomm/java/android/telecomm/InCallCall.java
@@ -40,6 +40,9 @@
     private final int mCapabilities;
     private final long mConnectTimeMillis;
     private final Uri mHandle;
+    private final int mHandlePresentation;
+    private final String mCallerDisplayName;
+    private final int mCallerDisplayNamePresentation;
     private final GatewayInfo mGatewayInfo;
     private final PhoneAccount mAccount;
     private final CallServiceDescriptor mCurrentCallServiceDescriptor;
@@ -47,7 +50,6 @@
     private RemoteCallVideoProvider mRemoteCallVideoProvider;
     private final String mParentCallId;
     private final List<String> mChildCallIds;
-    private final int mFeatures;
     private final StatusHints mStatusHints;
 
     /** @hide */
@@ -60,13 +62,15 @@
             int capabilities,
             long connectTimeMillis,
             Uri handle,
+            int handlePresentation,
+            String callerDisplayName,
+            int callerDisplayNamePresentation,
             GatewayInfo gatewayInfo,
             PhoneAccount account,
             CallServiceDescriptor descriptor,
             ICallVideoProvider callVideoProvider,
             String parentCallId,
             List<String> childCallIds,
-            int features,
             StatusHints statusHints) {
         mId = id;
         mState = state;
@@ -76,13 +80,15 @@
         mCapabilities = capabilities;
         mConnectTimeMillis = connectTimeMillis;
         mHandle = handle;
+        mHandlePresentation = handlePresentation;
+        mCallerDisplayName = callerDisplayName;
+        mCallerDisplayNamePresentation = callerDisplayNamePresentation;
         mGatewayInfo = gatewayInfo;
         mAccount = account;
         mCurrentCallServiceDescriptor = descriptor;
         mCallVideoProvider = callVideoProvider;
         mParentCallId = parentCallId;
         mChildCallIds = childCallIds;
-        mFeatures = features;
         mStatusHints = statusHints;
     }
 
@@ -134,6 +140,21 @@
         return mHandle;
     }
 
+    /** The {@link CallPropertyPresentation} which controls how the handle is shown. */
+    public int getHandlePresentation() {
+        return mHandlePresentation;
+    }
+
+    /** The endpoint to which the call is connected. */
+    public String getCallerDisplayName() {
+        return mCallerDisplayName;
+    }
+
+    /** The {@link CallPropertyPresentation} which controls how the caller display name is shown. */
+    public int getCallerDisplayNamePresentation() {
+        return mCallerDisplayNamePresentation;
+    }
+
     /** Gateway information for the call. */
     public GatewayInfo getGatewayInfo() {
         return mGatewayInfo;
@@ -183,15 +204,6 @@
     }
 
     /**
-     * The features of this call (e.g. VoLTE, VoWIFI).
-     *
-     * @return Features.
-     */
-    public int getFeatures() {
-        return mFeatures;
-    }
-
-    /**
      * The status label and icon.
      *
      * @return Status hints.
@@ -215,6 +227,9 @@
             int capabilities = source.readInt();
             long connectTimeMillis = source.readLong();
             Uri handle = source.readParcelable(classLoader);
+            int handlePresentation = source.readInt();
+            String callerDisplayName = source.readString();
+            int callerDisplayNamePresentation = source.readInt();
             GatewayInfo gatewayInfo = source.readParcelable(classLoader);
             PhoneAccount account = source.readParcelable(classLoader);
             CallServiceDescriptor descriptor = source.readParcelable(classLoader);
@@ -223,11 +238,11 @@
             String parentCallId = source.readString();
             List<String> childCallIds = new ArrayList<>();
             source.readList(childCallIds, classLoader);
-            int features = source.readInt();
             StatusHints statusHints = source.readParcelable(classLoader);
             return new InCallCall(id, state, disconnectCauseCode, disconnectCauseMsg,
-                    cannedSmsResponses, capabilities, connectTimeMillis, handle, gatewayInfo,
-                    account, descriptor, callVideoProvider, parentCallId, childCallIds, features,
+                    cannedSmsResponses, capabilities, connectTimeMillis, handle, handlePresentation,
+                    callerDisplayName, callerDisplayNamePresentation, gatewayInfo,
+                    account, descriptor, callVideoProvider, parentCallId, childCallIds,
                     statusHints);
         }
 
@@ -254,6 +269,9 @@
         destination.writeInt(mCapabilities);
         destination.writeLong(mConnectTimeMillis);
         destination.writeParcelable(mHandle, 0);
+        destination.writeInt(mHandlePresentation);
+        destination.writeString(mCallerDisplayName);
+        destination.writeInt(mCallerDisplayNamePresentation);
         destination.writeParcelable(mGatewayInfo, 0);
         destination.writeParcelable(mAccount, 0);
         destination.writeParcelable(mCurrentCallServiceDescriptor, 0);
@@ -261,7 +279,6 @@
                 mCallVideoProvider != null ? mCallVideoProvider.asBinder() : null);
         destination.writeString(mParentCallId);
         destination.writeList(mChildCallIds);
-        destination.writeInt(mFeatures);
         destination.writeParcelable(mStatusHints, 0);
     }
 
diff --git a/telecomm/java/android/telecomm/RemoteConnection.java b/telecomm/java/android/telecomm/RemoteConnection.java
index 8ef283a..3475305 100644
--- a/telecomm/java/android/telecomm/RemoteConnection.java
+++ b/telecomm/java/android/telecomm/RemoteConnection.java
@@ -37,9 +37,11 @@
         void onRequestingRingback(RemoteConnection connection, boolean ringback);
         void onCallCapabilitiesChanged(RemoteConnection connection, int callCapabilities);
         void onPostDialWait(RemoteConnection connection, String remainingDigits);
-        void onFeaturesChanged(RemoteConnection connection, int features);
-        void onSetAudioModeIsVoip(RemoteConnection connection, boolean isVoip);
-        void onSetStatusHints(RemoteConnection connection, StatusHints statusHints);
+        void onAudioModeIsVoipChanged(RemoteConnection connection, boolean isVoip);
+        void onStatusHintsChanged(RemoteConnection connection, StatusHints statusHints);
+        void onHandleChanged(RemoteConnection connection, Uri handle, int presentation);
+        void onCallerDisplayNameChanged(
+                RemoteConnection connection, String callerDisplayName, int presentation);
         void onDestroyed(RemoteConnection connection);
     }
 
@@ -53,9 +55,12 @@
     private boolean mRequestingRingback;
     private boolean mConnected;
     private int mCallCapabilities;
-    private int mFeatures;
     private boolean mAudioModeIsVoip;
     private StatusHints mStatusHints;
+    private Uri mHandle;
+    private int mHandlePresentation;
+    private String mCallerDisplayName;
+    private int mCallerDisplayNamePresentation;
 
     /**
      * @hide
@@ -91,10 +96,6 @@
         return mCallCapabilities;
     }
 
-    public int getFeatures() {
-        return mFeatures;
-    }
-
     public boolean getAudioModeIsVoip() {
         return mAudioModeIsVoip;
     }
@@ -103,6 +104,22 @@
         return mStatusHints;
     }
 
+    public Uri getHandle() {
+        return mHandle;
+    }
+
+    public int getHandlePresentation() {
+        return mHandlePresentation;
+    }
+
+    public String getCallerDisplayName() {
+        return mCallerDisplayName;
+    }
+
+    public int getCallerDisplayNamePresentation() {
+        return mCallerDisplayNamePresentation;
+    }
+
     public void abort() {
         try {
             if (mConnected) {
@@ -184,6 +201,15 @@
         }
     }
 
+    public void swapWithBackgroundCall() {
+        try {
+            if (mConnected) {
+                mConnectionService.swapWithBackgroundCall(mConnectionId);
+            }
+        } catch (RemoteException ignored) {
+        }
+    }
+
     public void setAudioState(CallAudioState state) {
         try {
             if (mConnected) {
@@ -271,21 +297,11 @@
         }
     }
 
-    /**
-     * @hide
-     */
-    void setFeatures(int features) {
-        mFeatures = features;
-        for (Listener l : mListeners) {
-            l.onFeaturesChanged(this, features);
-        }
-    }
-
     /** @hide */
     void setAudioModeIsVoip(boolean isVoip) {
         mAudioModeIsVoip = isVoip;
         for (Listener l : mListeners) {
-            l.onSetAudioModeIsVoip(this, isVoip);
+            l.onAudioModeIsVoipChanged(this, isVoip);
         }
     }
 
@@ -293,7 +309,25 @@
     void setStatusHints(StatusHints statusHints) {
         mStatusHints = statusHints;
         for (Listener l : mListeners) {
-            l.onSetStatusHints(this, statusHints);
+            l.onStatusHintsChanged(this, statusHints);
+        }
+    }
+
+    /** @hide */
+    void setHandle(Uri handle, int presentation) {
+        mHandle = handle;
+        mHandlePresentation = presentation;
+        for (Listener l : mListeners) {
+            l.onHandleChanged(this, handle, presentation);
+        }
+    }
+
+    /** @hide */
+    void setCallerDisplayName(String callerDisplayName, int presentation) {
+        mCallerDisplayName = callerDisplayName;
+        mCallerDisplayNamePresentation = presentation;
+        for (Listener l : mListeners) {
+            l.onCallerDisplayNameChanged(this, callerDisplayName, presentation);
         }
     }
 }
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index c22005b..a436af2 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -50,13 +50,11 @@
 
     private final IConnectionServiceAdapter mAdapter = new IConnectionServiceAdapter.Stub() {
 
-        /** ${inheritDoc} */
         @Override
         public void notifyIncomingCall(ConnectionRequest request) {
             Log.w(this, "notifyIncomingCall not implemented in Remote connection");
         }
 
-        /** ${inheritDoc} */
         @Override
         public void handleSuccessfulOutgoingCall(ConnectionRequest request) {
             if (isPendingConnection(request.getCallId())) {
@@ -66,7 +64,6 @@
             }
         }
 
-        /** ${inheritDoc} */
         @Override
         public void handleFailedOutgoingCall(
                 ConnectionRequest request, int errorCode, String errorMessage) {
@@ -77,7 +74,6 @@
             }
         }
 
-        /** ${inheritDoc} */
         @Override
         public void cancelOutgoingCall(ConnectionRequest request) {
             if (isPendingConnection(request.getCallId())) {
@@ -87,7 +83,6 @@
             }
         }
 
-        /** ${inheritDoc} */
         @Override
         public void setActive(String connectionId) {
             if (isCurrentConnection(connectionId)) {
@@ -95,7 +90,6 @@
             }
         }
 
-        /** ${inheritDoc} */
         @Override
         public void setRinging(String connectionId) {
             if (isCurrentConnection(connectionId)) {
@@ -103,13 +97,12 @@
             }
         }
 
-        /** ${inheritDoc} */
+        @Override
         public void setCallVideoProvider(
                 String connectionId, ICallVideoProvider callVideoProvider) {
             // not supported for remote connections.
         }
 
-        /** ${inheritDoc} */
         @Override
         public void setDialing(String connectionId) {
             if (isCurrentConnection(connectionId)) {
@@ -117,7 +110,6 @@
             }
         }
 
-        /** ${inheritDoc} */
         @Override
         public void setDisconnected(
                 String connectionId, int disconnectCause, String disconnectMessage) {
@@ -126,7 +118,6 @@
             }
         }
 
-        /** ${inheritDoc} */
         @Override
         public void setOnHold(String connectionId) {
             if (isCurrentConnection(connectionId)) {
@@ -134,7 +125,6 @@
             }
         }
 
-        /** ${inheritDoc} */
         @Override
         public void setRequestingRingback(String connectionId, boolean isRequestingRingback) {
             if (isCurrentConnection(connectionId)) {
@@ -142,7 +132,6 @@
             }
         }
 
-        /** ${inheritDoc} */
         @Override
         public void setCallCapabilities(String connectionId, int callCapabilities) {
             if (isCurrentConnection(connectionId)) {
@@ -150,19 +139,16 @@
             }
         }
 
-        /** ${inheritDoc} */
         @Override
         public void setIsConferenced(String connectionId, String conferenceConnectionId) {
             // not supported for remote connections.
         }
 
-        /** ${inheritDoc} */
         @Override
         public void addConferenceCall(String connectionId) {
             // not supported for remote connections.
         }
 
-        /** ${inheritDoc} */
         @Override
         public void removeCall(String connectionId) {
             if (isCurrentConnection(connectionId)) {
@@ -170,7 +156,6 @@
             }
         }
 
-        /** ${inheritDoc} */
         @Override
         public void onPostDialWait(String connectionId, String remainingDigits) {
             if (isCurrentConnection(connectionId)) {
@@ -178,7 +163,6 @@
             }
         }
 
-        /** ${inheritDoc} */
         @Override
         public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
             try {
@@ -188,15 +172,6 @@
             }
         }
 
-        /** ${inheritDoc} */
-        @Override
-        public void setFeatures(String connectionId, int features) {
-            if (isCurrentConnection(connectionId)) {
-                mConnection.setFeatures(features);
-            }
-        }
-
-        /** ${inheritDoc} */
         @Override
         public final void setAudioModeIsVoip(String connectionId, boolean isVoip) {
             if (isCurrentConnection(connectionId)) {
@@ -204,13 +179,27 @@
             }
         }
 
-        /** ${inheritDoc} */
         @Override
         public final void setStatusHints(String connectionId, StatusHints statusHints) {
             if (isCurrentConnection(connectionId)) {
                 mConnection.setStatusHints(statusHints);
             }
         }
+
+        @Override
+        public final void setHandle(String connectionId, Uri handle, int presentation) {
+            if (isCurrentConnection(connectionId)) {
+                mConnection.setHandle(handle, presentation);
+            }
+        }
+
+        @Override
+        public final void setCallerDisplayName(
+                String connectionId, String callerDisplayName, int presentation) {
+            if (isCurrentConnection(connectionId)) {
+                mConnection.setCallerDisplayName(callerDisplayName, presentation);
+            }
+        }
     };
 
     RemoteConnectionService(ComponentName componentName, IConnectionService connectionService)
@@ -246,8 +235,13 @@
 
         if (mConnectionId == null) {
             String id = UUID.randomUUID().toString();
-            ConnectionRequest newRequest = new ConnectionRequest(request.getAccount(), id,
-                    request.getHandle(), request.getExtras(), request.getVideoState());
+            ConnectionRequest newRequest = new ConnectionRequest(
+                    request.getAccount(),
+                    id,
+                    request.getHandle(),
+                    request.getHandlePresentation(),
+                    request.getExtras(),
+                    request.getVideoState());
             try {
                 mConnectionService.call(newRequest);
                 mConnectionId = id;
diff --git a/telecomm/java/android/telecomm/StatusHints.java b/telecomm/java/android/telecomm/StatusHints.java
index 354dc36..5e64bff 100644
--- a/telecomm/java/android/telecomm/StatusHints.java
+++ b/telecomm/java/android/telecomm/StatusHints.java
@@ -21,6 +21,7 @@
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.DisplayMetrics;
@@ -35,11 +36,13 @@
     private final ComponentName mComponentName;
     private final String mLabel;
     private final int mIconId;
+    private final Bundle mExtras;
 
-    public StatusHints(ComponentName componentName, String label, int iconId) {
+    public StatusHints(ComponentName componentName, String label, int iconId, Bundle extras) {
         mComponentName = componentName;
         mLabel = label;
         mIconId = iconId;
+        mExtras = extras;
     }
 
     /**
@@ -70,6 +73,13 @@
         return getIcon(context, mIconId);
     }
 
+    /**
+     * @return Extra data used to display status.
+     */
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -80,6 +90,7 @@
         out.writeParcelable(mComponentName, flags);
         out.writeString(mLabel);
         out.writeInt(mIconId);
+        out.writeParcelable(mExtras, 0);
     }
 
     public static final Creator<StatusHints> CREATOR
@@ -97,6 +108,7 @@
         mComponentName = in.readParcelable(getClass().getClassLoader());
         mLabel = in.readString();
         mIconId = in.readInt();
+        mExtras = (Bundle) in.readParcelable(getClass().getClassLoader());
     }
 
     private Drawable getIcon(Context context, int resId) {
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
index c8ce4c6..16d2edf 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
@@ -58,6 +58,8 @@
 
     void splitFromConference(String callId);
 
+    void swapWithBackgroundCall(String callId);
+
     void onPostDialContinue(String callId, boolean proceed);
 
     void onPhoneAccountClicked(String callId);
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
index e724bfb..bc67eab 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
@@ -16,6 +16,7 @@
 
 package com.android.internal.telecomm;
 
+import android.net.Uri;
 import android.telecomm.ConnectionRequest;
 import android.telecomm.StatusHints;
 
@@ -64,9 +65,11 @@
 
     void setCallVideoProvider(String callId, ICallVideoProvider callVideoProvider);
 
-    void setFeatures(String callId, int features);
-
     void setAudioModeIsVoip(String callId, boolean isVoip);
 
     void setStatusHints(String callId, in StatusHints statusHints);
+
+    void setHandle(String callId, in Uri handle, int presentation);
+
+    void setCallerDisplayName(String callId, String callerDisplayName, int presentation);
 }
diff --git a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
index 7f3767c..ce0309f 100644
--- a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
@@ -51,4 +51,6 @@
     void conference(String callId);
 
     void splitFromConference(String callId);
+
+    void swapWithBackgroundCall(String callId);
 }