Merge "API support for reporting of changes to call features. (eg VoLTE, VoWIFI, etc)"
diff --git a/api/current.txt b/api/current.txt
index ed035e0..a39bc79 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -27451,6 +27451,12 @@
     field public static final int SWAP_CALLS = 8; // 0x8
   }
 
+  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 CallInfo implements android.os.Parcelable {
     ctor public CallInfo(java.lang.String, android.telecomm.CallState, android.net.Uri);
     method public int describeContents();
@@ -27487,6 +27493,7 @@
     method protected void onAdapterAttached(android.telecomm.CallServiceAdapter);
     method public abstract void onAudioStateChanged(java.lang.String, android.telecomm.CallAudioState);
     method public final android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onFeaturesChanged(java.lang.String, int);
     method public void onPostDialContinue(java.lang.String, boolean);
     method public abstract void playDtmfTone(java.lang.String, char);
     method public abstract void reject(java.lang.String);
@@ -27508,6 +27515,7 @@
     method public void setCallVideoProvider(java.lang.String, android.telecomm.CallVideoProvider);
     method public void setDialing(java.lang.String);
     method public void setDisconnected(java.lang.String, int, java.lang.String);
+    method public void setFeatures(java.lang.String, int);
     method public void setOnHold(java.lang.String);
     method public void setRequestingRingback(java.lang.String, boolean);
     method public void setRinging(java.lang.String);
@@ -27591,6 +27599,7 @@
     ctor protected Connection();
     method public final android.telecomm.CallAudioState getCallAudioState();
     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 android.telecomm.Connection getParentConnection();
     method public final int getState();
@@ -27616,6 +27625,7 @@
     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 setIsConferenceCapable(boolean);
     method public final void setOnHold();
@@ -27627,6 +27637,35 @@
     method public static java.lang.String stateToString(int);
   }
 
+  public static abstract interface Connection.Listener {
+    method public abstract void onAudioStateChanged(android.telecomm.Connection, android.telecomm.CallAudioState);
+    method public abstract void onConferenceCapableChanged(android.telecomm.Connection, boolean);
+    method public abstract void onDestroyed(android.telecomm.Connection);
+    method public abstract void onDisconnected(android.telecomm.Connection, int, java.lang.String);
+    method public abstract void onFeaturesChanged(android.telecomm.Connection, int);
+    method public abstract void onHandleChanged(android.telecomm.Connection, android.net.Uri);
+    method public abstract void onParentConnectionChanged(android.telecomm.Connection, android.telecomm.Connection);
+    method public abstract void onRequestingRingback(android.telecomm.Connection, boolean);
+    method public abstract void onSetCallVideoProvider(android.telecomm.Connection, android.telecomm.CallVideoProvider);
+    method public abstract void onSignalChanged(android.telecomm.Connection, android.os.Bundle);
+    method public abstract void onStateChanged(android.telecomm.Connection, int);
+  }
+
+  public static class Connection.ListenerBase implements android.telecomm.Connection.Listener {
+    ctor public Connection.ListenerBase();
+    method public void onAudioStateChanged(android.telecomm.Connection, android.telecomm.CallAudioState);
+    method public void onConferenceCapableChanged(android.telecomm.Connection, boolean);
+    method public void onDestroyed(android.telecomm.Connection);
+    method public void onDisconnected(android.telecomm.Connection, int, java.lang.String);
+    method public void onFeaturesChanged(android.telecomm.Connection, int);
+    method public void onHandleChanged(android.telecomm.Connection, android.net.Uri);
+    method public void onParentConnectionChanged(android.telecomm.Connection, android.telecomm.Connection);
+    method public void onRequestingRingback(android.telecomm.Connection, boolean);
+    method public void onSetCallVideoProvider(android.telecomm.Connection, android.telecomm.CallVideoProvider);
+    method public void onSignalChanged(android.telecomm.Connection, android.os.Bundle);
+    method public void onStateChanged(android.telecomm.Connection, int);
+  }
+
   public final class Connection.State {
     field public static final int ACTIVE = 3; // 0x3
     field public static final int DIALING = 2; // 0x2
@@ -27666,6 +27705,9 @@
     method protected void onCreateConferenceConnection(java.lang.String, android.telecomm.Connection, android.telecomm.Response<java.lang.String, android.telecomm.Connection>);
     method protected void onCreateConnections(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.OutgoingCallResponse<android.telecomm.Connection>);
     method protected void onCreateIncomingConnection(android.telecomm.ConnectionRequest, android.telecomm.Response<android.telecomm.ConnectionRequest, android.telecomm.Connection>);
+    method public final void onFeaturesChanged(java.lang.String, int);
+    method public final void onPostDialContinue(java.lang.String, boolean);
+    method public final void onPostDialWait(android.telecomm.Connection, java.lang.String);
     method public final void playDtmfTone(java.lang.String, char);
     method public final void reject(java.lang.String);
     method public final void setIncomingCallId(java.lang.String, android.os.Bundle);
@@ -27712,6 +27754,7 @@
     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 android.telecomm.CallServiceDescriptor getHandoffCallServiceDescriptor();
diff --git a/telecomm/java/android/telecomm/CallFeatures.java b/telecomm/java/android/telecomm/CallFeatures.java
new file mode 100644
index 0000000..076d25a
--- /dev/null
+++ b/telecomm/java/android/telecomm/CallFeatures.java
@@ -0,0 +1,29 @@
+/*
+ * 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/CallService.java b/telecomm/java/android/telecomm/CallService.java
index d2caca0..44380e2 100644
--- a/telecomm/java/android/telecomm/CallService.java
+++ b/telecomm/java/android/telecomm/CallService.java
@@ -408,4 +408,16 @@
     public abstract void splitFromConference(String callId);
 
     public void onPostDialContinue(String callId, boolean proceed) {}
+
+    public void onPostDialWait(Connection conn, String remaining) {}
+
+    /**
+     * Called when changes to the features of a call occurs. Features are defined in
+     * {@link android.telecomm.CallFeatures}.  The active features for the call are represented as
+     * bits in the features bit-mask.
+     *
+     * @param callId The call to set the features for.
+     * @param features The new features of the call.
+     */
+    public abstract void onFeaturesChanged(String callId, int features);
 }
diff --git a/telecomm/java/android/telecomm/CallServiceAdapter.java b/telecomm/java/android/telecomm/CallServiceAdapter.java
index 8412e80..1b3c0a3 100644
--- a/telecomm/java/android/telecomm/CallServiceAdapter.java
+++ b/telecomm/java/android/telecomm/CallServiceAdapter.java
@@ -354,4 +354,22 @@
             }
         }
     }
+
+    /**
+    * 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.
+    */
+    public void setFeatures(String callId, int features) {
+        Log.v(this, "setFeatures: %d", features);
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.setFeatures(callId, features);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
 }
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index f80e4a9..73aac2c 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -34,6 +34,7 @@
     /** @hide */
     public interface Listener {
         void onStateChanged(Connection c, int state);
+        void onFeaturesChanged(Connection c, int features);
         void onAudioStateChanged(Connection c, CallAudioState state);
         void onHandleChanged(Connection c, Uri newHandle);
         void onSignalChanged(Connection c, Bundle details);
@@ -51,6 +52,11 @@
         @Override
         public void onStateChanged(Connection c, int state) {}
 
+        /** {@inheritDoc} */
+        @Override
+        public void onFeaturesChanged(Connection c, int features) {}
+
+        /** {@inheritDoc} */
          @Override
         public void onAudioStateChanged(Connection c, CallAudioState state) {}
 
@@ -97,6 +103,7 @@
     private final List<Connection> mChildConnections = new ArrayList<>();
 
     private int mState = State.NEW;
+    private int mFeatures = CallFeatures.NONE;
     private CallAudioState mCallAudioState;
     private Uri mHandle;
     private boolean mRequestingRingback = false;
@@ -131,6 +138,12 @@
     }
 
     /**
+     * @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.
@@ -284,6 +297,22 @@
     }
 
     /**
+     * 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.
+     *
+     * @param features The features active.
+     */
+    public final void setFeatures(int features) {
+        Log.d(this, "setFeatures %d", features);
+        this.mFeatures = features;
+        for (Listener l : mListeners) {
+            l.onFeaturesChanged(this, mFeatures);
+        }
+    }
+
+    /**
      * Inform this Connection that the state of its audio output has been changed externally.
      *
      * @param state The new audio state.
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index e68efea..530e977 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -108,6 +108,14 @@
             }
         }
 
+        /** {@inheritDoc} */
+        @Override
+        public void onFeaturesChanged(Connection c, int features) {
+            String id = mIdByConnection.get(c);
+            Log.d(this, "Adapter set features %d", features);
+            getAdapter().setFeatures(id, features);
+        }
+
         @Override
         public void onDisconnected(Connection c, int cause, String message) {
             String id = mIdByConnection.get(c);
@@ -561,4 +569,18 @@
         Log.w(this, "%s - Cannot find Connection %s", action, callId);
         return NULL_CONNECTION;
     }
+
+    /**
+     * Handles changes to the features of a connection.
+     * Features are defined in {@link android.telecomm.CallFeatures} and are passed in as a
+     * bit-mask.
+     *
+     * @param callId The call to set the features for.
+     * @param features The new features of the call.
+     */
+    @Override
+    public final void onFeaturesChanged(String callId, int features) {
+        Log.d(this, "onFeaturesChanged %s %d", callId, features);
+        findConnectionForAction(callId, "onFeaturesChanged").setFeatures(features);
+    }
 }
diff --git a/telecomm/java/android/telecomm/InCallCall.java b/telecomm/java/android/telecomm/InCallCall.java
index cf31cec5..44dd567 100644
--- a/telecomm/java/android/telecomm/InCallCall.java
+++ b/telecomm/java/android/telecomm/InCallCall.java
@@ -48,6 +48,7 @@
     private RemoteCallVideoProvider mRemoteCallVideoProvider;
     private final String mParentCallId;
     private final List<String> mChildCallIds;
+    private final int mFeatures;
 
     /** @hide */
     public InCallCall(
@@ -65,7 +66,8 @@
             CallServiceDescriptor handoffDescriptor,
             ICallVideoProvider callVideoProvider,
             String parentCallId,
-            List<String> childCallIds) {
+            List<String> childCallIds,
+            int features) {
         mId = id;
         mState = state;
         mDisconnectCauseCode = disconnectCauseCode;
@@ -81,6 +83,7 @@
         mCallVideoProvider = callVideoProvider;
         mParentCallId = parentCallId;
         mChildCallIds = childCallIds;
+        mFeatures = features;
     }
 
     /** The unique ID of the call. */
@@ -187,6 +190,15 @@
         return mChildCallIds;
     }
 
+    /**
+     * The features of this call (e.g. VoLTE, VoWIFI).
+     *
+     * @return Features.
+     */
+    public int getFeatures() {
+        return mFeatures;
+    }
+
     /** Responsible for creating InCallCall objects for deserialized Parcels. */
     public static final Parcelable.Creator<InCallCall> CREATOR =
             new Parcelable.Creator<InCallCall> () {
@@ -211,10 +223,11 @@
             String parentCallId = source.readString();
             List<String> childCallIds = new ArrayList<>();
             source.readList(childCallIds, classLoader);
+            int features = source.readInt();
             return new InCallCall(id, state, disconnectCauseCode, disconnectCauseMsg,
                     cannedSmsResponses, capabilities, connectTimeMillis, handle, gatewayInfo,
                     subscription, descriptor, handoffDescriptor, callVideoProvider, parentCallId,
-                    childCallIds);
+                    childCallIds, features);
         }
 
         @Override
@@ -248,6 +261,7 @@
                 mCallVideoProvider != null ? mCallVideoProvider.asBinder() : null);
         destination.writeString(mParentCallId);
         destination.writeList(mChildCallIds);
+        destination.writeInt(mFeatures);
     }
 
     @Override
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index 02a100e..f6fc69f 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -193,6 +193,12 @@
             } catch (RemoteException e) {
             }
         }
+
+        /** ${inheritDoc} */
+        @Override
+        public void setFeatures(String connectionId, int features) {
+            // not supported for remote connections.
+        }
     };
 
     RemoteConnectionService(ComponentName componentName, ICallService callService)
diff --git a/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl b/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
index b81ef37..e78762d 100644
--- a/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
@@ -65,4 +65,6 @@
     void queryRemoteConnectionServices(RemoteServiceCallback callback);
 
     void setCallVideoProvider(String callId, ICallVideoProvider callVideoProvider);
+
+    void setFeatures(String callId, int features);
 }