Pass onPostDialChar call back from Telephony to Telecom.

Add plumbing to alert Telecom every time a character is processed after
the post dial wait state (the processing happens in Telephony).

Bug: 18644688
Change-Id: I487d76aa9c959ca528c6377374aa35c2d0b4a803
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index f3b0586..a180f44 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -246,6 +246,7 @@
         public void onVideoStateChanged(Connection c, int videoState) {}
         public void onDisconnected(Connection c, DisconnectCause disconnectCause) {}
         public void onPostDialWait(Connection c, String remaining) {}
+        public void onPostDialChar(Connection c, char nextChar) {}
         public void onRingbackRequested(Connection c, boolean ringback) {}
         public void onDestroyed(Connection c) {}
         public void onConnectionCapabilitiesChanged(Connection c, int capabilities) {}
@@ -998,6 +999,23 @@
     }
 
     /**
+     * Informs listeners that this {@code Connection} has processed a character in the post-dial
+     * started state. This is done when (a) the {@code Connection} is issuing a DTMF sequence;
+     * (b) it has encountered a "wait" character; and (c) it wishes to signal Telecom to play
+     * the corresponding DTMF tone locally.
+     *
+     * @param nextChar The DTMF character that was just processed by the {@code Connection}.
+     *
+     * @hide
+     */
+    public final void setNextPostDialWaitChar(char nextChar) {
+        checkImmutable();
+        for (Listener l : mListeners) {
+            l.onPostDialChar(this, nextChar);
+        }
+    }
+
+    /**
      * Requests that the framework play a ringback tone. This is to be invoked by implementations
      * that do not play a ringback tone themselves in the connection's audio stream.
      *
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index d0a8aee..df16375 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -484,6 +484,13 @@
         }
 
         @Override
+        public void onPostDialChar(Connection c, char nextChar) {
+            String id = mIdByConnection.get(c);
+            Log.d(this, "Adapter onPostDialChar %s, %s", c, nextChar);
+            mAdapter.onPostDialChar(id, nextChar);
+        }
+
+        @Override
         public void onRingbackRequested(Connection c, boolean ringback) {
             String id = mIdByConnection.get(c);
             Log.d(this, "Adapter onRingback %b", ringback);
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index aee9675..d026a28 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -226,6 +226,15 @@
         }
     }
 
+    void onPostDialChar(String callId, char nextChar) {
+        for (IConnectionServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.onPostDialChar(callId, nextChar);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
     /**
      * Indicates that a new conference call has been created.
      *
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index 7619da5..429f296 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -58,6 +58,7 @@
     private static final int MSG_SET_CALLER_DISPLAY_NAME = 19;
     private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 20;
     private static final int MSG_ADD_EXISTING_CONNECTION = 21;
+    private static final int MSG_ON_POST_DIAL_CHAR = 22;
 
     private final IConnectionServiceAdapter mDelegate;
 
@@ -143,6 +144,15 @@
                     }
                     break;
                 }
+                case MSG_ON_POST_DIAL_CHAR: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        mDelegate.onPostDialChar((String) args.arg1, (char) args.argi1);
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
                 case MSG_QUERY_REMOTE_CALL_SERVICES:
                     mDelegate.queryRemoteConnectionServices((RemoteServiceCallback) msg.obj);
                     break;
@@ -299,6 +309,14 @@
         }
 
         @Override
+        public void onPostDialChar(String connectionId, char nextChar) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = connectionId;
+            args.argi1 = nextChar;
+            mHandler.obtainMessage(MSG_ON_POST_DIAL_CHAR, args).sendToTarget();
+        }
+
+        @Override
         public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
             mHandler.obtainMessage(MSG_QUERY_REMOTE_CALL_SERVICES, callback).sendToTarget();
         }
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 95cc387..486691f 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -101,6 +101,15 @@
         public void onPostDialWait(RemoteConnection connection, String remainingPostDialSequence) {}
 
         /**
+         * Invoked when the post-dial sequence in the outgoing {@code Connection} has processed
+         * a character.
+         *
+         * @param connection The {@code RemoteConnection} invoking this method.
+         * @param nextChar The character being processed.
+         */
+        public void onPostDialChar(RemoteConnection connection, char nextChar) {}
+
+        /**
          * Indicates that the VOIP audio status of this {@code RemoteConnection} has changed.
          * See {@link #isVoipAudioMode()}.
          *
@@ -726,7 +735,7 @@
      * of time.
      *
      * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
-     * {@code RemoteConnection} will pause playing the tones and notify callbackss via
+     * {@code RemoteConnection} will pause playing the tones and notify callbacks via
      * {@link Callback#onPostDialWait(RemoteConnection, String)}. At this point, the in-call app
      * should display to the user an indication of this state and an affordance to continue
      * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
@@ -869,6 +878,15 @@
     /**
      * @hide
      */
+    void onPostDialChar(char nextChar) {
+        for (Callback c : mCallbacks) {
+            c.onPostDialChar(this, nextChar);
+        }
+    }
+
+    /**
+     * @hide
+     */
     void setVideoState(int videoState) {
         mVideoState = videoState;
         for (Callback c : mCallbacks) {
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index 906ecaa..073dcd5f 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -223,6 +223,12 @@
         }
 
         @Override
+        public void onPostDialChar(String callId, char nextChar) {
+            findConnectionForAction(callId, "onPostDialChar")
+                    .onPostDialChar(nextChar);
+        }
+
+        @Override
         public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
             // Not supported from remote connection service.
         }