am 1182a111: am 5788f2ba: am ae5708db: am c4aee98a: Improve error handling in listener services.

* commit '1182a111ece20707da9b689ada28af190a2ee41a':
  Improve error handling in listener services.
diff --git a/Android.mk b/Android.mk
index d478a59..26e1b56 100644
--- a/Android.mk
+++ b/Android.mk
@@ -272,11 +272,14 @@
 	media/java/android/media/IRemoteDisplayProvider.aidl \
 	media/java/android/media/IRemoteVolumeObserver.aidl \
 	media/java/android/media/IRingtonePlayer.aidl \
+	telephony/java/com/android/internal/telephony/ICallService.aidl \
+	telephony/java/com/android/internal/telephony/ICallServiceAdapter.aidl \
 	telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \
 	telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
 	telephony/java/com/android/internal/telephony/ITelephony.aidl \
 	telephony/java/com/android/internal/telephony/IThirdPartyCallListener.aidl \
 	telephony/java/com/android/internal/telephony/IThirdPartyCallProvider.aidl \
+	telephony/java/com/android/internal/telephony/IThirdPartyCallSendDtmfCallback.aidl \
 	telephony/java/com/android/internal/telephony/IThirdPartyCallService.aidl \
 	telephony/java/com/android/internal/telephony/ISms.aidl \
 	telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
diff --git a/api/current.txt b/api/current.txt
index 333c6fa..6fb9d77 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -24513,12 +24513,14 @@
     method public java.lang.String getSubscriberId();
     method public java.lang.String getVoiceMailAlphaTag();
     method public java.lang.String getVoiceMailNumber();
+    method public int getWhenToMakeWifiCalls();
     method public boolean hasIccCard();
     method public boolean iccCloseLogicalChannel(int);
     method public int iccOpenLogicalChannel(java.lang.String);
     method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
     method public boolean isNetworkRoaming();
     method public void listen(android.telephony.PhoneStateListener, int);
+    method public void newIncomingThirdPartyCall(android.content.ComponentName, java.lang.String, java.lang.String);
     field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
     field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
     field public static final int CALL_STATE_IDLE = 0; // 0x0
@@ -24582,7 +24584,12 @@
     method public void hangup();
     method public void incomingCallAccept();
     method public void mute(boolean);
-    method public void sendDtmf(char);
+    method public void sendDtmf(char, android.telephony.ThirdPartyCallSendDtmfCallback);
+  }
+
+  public class ThirdPartyCallSendDtmfCallback {
+    ctor public ThirdPartyCallSendDtmfCallback(com.android.internal.telephony.IThirdPartyCallSendDtmfCallback);
+    method public void onSendDtmfCompleted();
   }
 
   public class ThirdPartyCallService {
@@ -34081,7 +34088,11 @@
     method public abstract void hangup() throws android.os.RemoteException;
     method public abstract void incomingCallAccept() throws android.os.RemoteException;
     method public abstract void mute(boolean) throws android.os.RemoteException;
-    method public abstract void sendDtmf(char) throws android.os.RemoteException;
+    method public abstract void sendDtmf(char, com.android.internal.telephony.IThirdPartyCallSendDtmfCallback) throws android.os.RemoteException;
+  }
+
+  public abstract interface IThirdPartyCallSendDtmfCallback implements android.os.IInterface {
+    method public abstract void onSendDtmfCompleted() throws android.os.RemoteException;
   }
 
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 9332578..d7f6a0b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2483,6 +2483,14 @@
             NOTIFICATION_SOUND
         };
 
+        /**
+         * When to use Wi-Fi calling
+         *
+         * @see android.telephony.TelephonyManager.WifiCallingChoices
+         * @hide
+         */
+        public static final String WHEN_TO_MAKE_WIFI_CALLS = "when_to_make_wifi_calls";
+
         // Settings moved to Settings.Secure
 
         /**
diff --git a/telephony/java/android/telephony/CallService.java b/telephony/java/android/telephony/CallService.java
new file mode 100644
index 0000000..0ea55b2
--- /dev/null
+++ b/telephony/java/android/telephony/CallService.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2013 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;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+
+import com.android.internal.telephony.ICallService;
+import com.android.internal.telephony.ICallServiceAdapter;
+
+/**
+ * Base implementation of CallService which can be used to provide calls for the system
+ * in-call UI. CallService is a one-way service from the framework's CallsManager to any app
+ * that would like to provide calls managed by the default system in-call user interface.
+ * When the service is bound by the framework, CallsManager will call setCallServiceAdapter
+ * which will provide CallService with an instance of {@link CallServiceAdapter} to be used
+ * for communicating back to CallsManager. Subsequently, more specific methods of the service
+ * will be called to perform various call actions including making an outgoing call and
+ * disconnected existing calls.
+ * TODO(santoscordon): Needs more about AndroidManifest.xml service registrations before
+ * we can unhide this API.
+ *
+ * Most public methods of this function are backed by a one-way AIDL interface which precludes
+ * syncronous responses. As a result, most responses are handled by (or have TODOs to handle)
+ * response objects instead of return values.
+ * TODO(santoscordon): Improve paragraph above once the final design is in place.
+ * @hide
+ */
+public abstract class CallService extends Service {
+
+    /**
+     * Default Handler used to consolidate binder method calls onto a single thread.
+     */
+    private final class CallServiceMessageHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SET_CALL_SERVICE_ADAPTER:
+                    setCallServiceAdapter((ICallServiceAdapter) msg.obj);
+                    break;
+                case MSG_IS_COMPATIBLE_WITH:
+                    isCompatibleWith((String) msg.obj);
+                    break;
+                case MSG_CALL:
+                    call((String) msg.obj);
+                    break;
+                case MSG_DISCONNECT:
+                    disconnect((String) msg.obj);
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Default ICallService implementation provided to CallsManager via {@link #onBind}.
+     */
+    private final class CallServiceWrapper extends ICallService.Stub {
+        @Override
+        public void setCallServiceAdapter(ICallServiceAdapter callServiceAdapter) {
+            mMessageHandler.obtainMessage(MSG_SET_CALL_SERVICE_ADAPTER, callServiceAdapter)
+                    .sendToTarget();
+        }
+
+        @Override
+        public void isCompatibleWith(String handle) {
+            mMessageHandler.obtainMessage(MSG_IS_COMPATIBLE_WITH, handle).sendToTarget();
+        }
+
+        @Override
+        public void call(String handle) {
+            mMessageHandler.obtainMessage(MSG_CALL, handle).sendToTarget();
+        }
+
+        @Override
+        public void disconnect(String callId) {
+            mMessageHandler.obtainMessage(MSG_DISCONNECT, callId).sendToTarget();
+        }
+    }
+
+    // Only used internally by this class.
+    // Binder method calls on this service can occur on multiple threads. These messages are used
+    // in conjunction with {@link #mMessageHandler} to ensure that all callbacks are handled on a
+    // single thread.  Keeping it on a single thread allows CallService implementations to avoid
+    // needing multi-threaded code in their own callback routines.
+    private static final int
+            MSG_SET_CALL_SERVICE_ADAPTER = 1,
+            MSG_IS_COMPATIBLE_WITH = 2,
+            MSG_CALL = 3,
+            MSG_DISCONNECT = 4;
+
+    /**
+     * Message handler for consolidating binder callbacks onto a single thread.
+     * See {@link #CallServiceMessageHandler}.
+     */
+    private final CallServiceMessageHandler mMessageHandler;
+
+    /**
+     * Default binder implementation of {@link ICallService} interface.
+     */
+    private final CallServiceWrapper mBinder;
+
+    /**
+     * Protected constructor called only by subclasses creates the binder interface and
+     * single-threaded message handler.
+     */
+    protected CallService() {
+        mMessageHandler = new CallServiceMessageHandler();
+        mBinder = new CallServiceWrapper();
+    }
+
+    /** {@inheritDoc} */
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    /**
+     * Sets an implementation of ICallServiceAdapter for adding new calls and communicating state
+     * changes of existing calls.
+     * @param callServiceAdapter Adapter object for communicating call to CallsManager
+     * TODO(santoscordon): Should we not reference ICallServiceAdapter directly from here? Should we
+     * wrap that in a wrapper like we do for CallService/ICallService?
+     * TODO(santoscordon): Consider rename of CallServiceAdapter to CallsManager.
+     */
+    public abstract void setCallServiceAdapter(ICallServiceAdapter callServiceAdapter);
+
+    /**
+     * Determines if the CallService can make calls to the handle.
+     * @param handle The handle to test for compatibility.
+     * TODO(santoscordon): Need response parameter.
+     */
+    public abstract void isCompatibleWith(String handle);
+
+    /**
+     * Calls the specified handle. Handle type is dynamically extensible and can be a phone number,
+     * a SIP address, or other types. Only called if {@link #isCompatibleWith} returns true for the
+     * same handle and this service is selected by the switchboard to handle the call.
+     * @param handle The handle to call.
+     */
+    public abstract void call(String handle);
+
+    /**
+     * Disconnects the specified call.
+     * @param callId The ID of the call to disconnect.
+     */
+    public abstract void disconnect(String callId);
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 3d416fb..ec1f1df 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ComponentName;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -61,6 +62,20 @@
     private static ITelephonyRegistry sRegistry;
     private final Context mContext;
 
+    /**
+     * The allowed states of Wi-Fi calling.
+     *
+     * @hide
+     */
+    public interface WifiCallingChoices {
+        /** Always use Wi-Fi calling */
+        static final int ALWAYS_USE = 0;
+        /** Ask the user whether to use Wi-Fi on every call */
+        static final int ASK_EVERY_TIME = 1;
+        /** Never use Wi-Fi calling */
+        static final int NEVER_USE = 2;
+    }
+
     /** @hide */
     public TelephonyManager(Context context) {
         Context appContext = context.getApplicationContext();
@@ -1422,6 +1437,24 @@
     }
 
     /**
+     * Inform the phone about a new incoming third party call. The phone will bind to the service
+     * identified by component to handle the call.
+     * @param component the component that should handle the intent.
+     * @param callId the unique id of the call. This id is passed to the service via {@link
+     *               ThirdPartyCallService#incomingCallAttach incomingCallAttach}.
+     * @param callerDisplayName the name shown to the user. Normally this will be the caller's phone
+     *                          number.
+     */
+    public void newIncomingThirdPartyCall(ComponentName component, String callId,
+            String callerDisplayName) {
+        try {
+            getITelephony().newIncomingThirdPartyCall(component, callId, callerDisplayName);
+        } catch (RemoteException ex) {
+        } catch (NullPointerException ex) {
+        }
+    }
+
+    /**
      * Returns the MMS user agent.
      */
     public String getMmsUserAgent() {
@@ -1599,4 +1632,31 @@
         }
         return false;
     }
+
+    /*
+     * Obtain the current state of Wi-Fi calling.
+     *
+     * @hide
+     * @see android.telephony.TelephonyManager.WifiCallingChoices
+     */
+    public int getWhenToMakeWifiCalls() {
+        try {
+            return getITelephony().getWhenToMakeWifiCalls();
+        } catch (RemoteException ex) {
+            return WifiCallingChoices.NEVER_USE;
+        }
+    }
+
+    /**
+     * Set the current state of Wi-Fi calling.
+     *
+     * @hide
+     * @see android.telephony.TelephonyManager.WifiCallingChoices
+     */
+    public void setWhenToMakeWifiCalls(int state) {
+        try {
+            getITelephony().setWhenToMakeWifiCalls(state);
+        } catch (RemoteException ex) {
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/ThirdPartyCallListener.java b/telephony/java/android/telephony/ThirdPartyCallListener.java
index 00265f8..08f8d3a 100644
--- a/telephony/java/android/telephony/ThirdPartyCallListener.java
+++ b/telephony/java/android/telephony/ThirdPartyCallListener.java
@@ -16,6 +16,8 @@
 
 package android.telephony;
 
+import android.os.Handler;
+import android.os.Message;
 import android.os.RemoteException;
 
 import com.android.internal.telephony.IThirdPartyCallListener;
@@ -27,15 +29,12 @@
 public class ThirdPartyCallListener {
     private final IThirdPartyCallListener mListener;
 
-    // Call end reason. TODO: rename this to DisconnectCause once they are public.
+    // Call end reason.
     public static final int CALL_END_NORMAL = 1;
     public static final int CALL_END_INCOMING_MISSED = 2;
     public static final int CALL_END_OTHER = 3;
 
     public ThirdPartyCallListener(IThirdPartyCallListener listener) {
-        if (listener == null) {
-            throw new IllegalArgumentException("Invalid listener");
-        }
         mListener = listener;
     }
 
@@ -45,7 +44,9 @@
      */
     public void onCallProviderAttached(ThirdPartyCallProvider callProvider) {
         try {
-            mListener.onCallProviderAttached(callProvider.getCallback());
+            if (mListener != null) {
+                mListener.onCallProviderAttached(callProvider.callback);
+            }
         } catch (RemoteException e) {
         }
     }
@@ -55,7 +56,9 @@
      */
     public void onRingingStarted() {
         try {
-            mListener.onRingingStarted();
+            if (mListener != null) {
+                mListener.onRingingStarted();
+            }
         } catch (RemoteException e) {
         }
     }
@@ -65,7 +68,9 @@
      */
     public void onCallEstablished() {
         try {
-            mListener.onCallEstablished();
+            if (mListener != null) {
+                mListener.onCallEstablished();
+            }
         } catch (RemoteException e) {
         }
     }
@@ -75,7 +80,9 @@
      */
     public void onCallEnded(int reason) {
         try {
-            mListener.onCallEnded(reason);
+            if (mListener != null) {
+                mListener.onCallEnded(reason);
+            }
         } catch (RemoteException e) {
         }
     }
diff --git a/telephony/java/android/telephony/ThirdPartyCallProvider.java b/telephony/java/android/telephony/ThirdPartyCallProvider.java
index bd8a1ea..5054380 100644
--- a/telephony/java/android/telephony/ThirdPartyCallProvider.java
+++ b/telephony/java/android/telephony/ThirdPartyCallProvider.java
@@ -20,6 +20,7 @@
 import android.os.Message;
 
 import com.android.internal.telephony.IThirdPartyCallProvider;
+import com.android.internal.telephony.IThirdPartyCallSendDtmfCallback;
 
 /**
  * Interface sent to {@link android.telephony.ThirdPartyCallListener#onCallProviderAttached
@@ -55,15 +56,11 @@
     /**
      * Sends the given DTMF code. The code can be '0'-'9', 'A'-'D', '#', or '*'.
      */
-    public void sendDtmf(char c) {
+    public void sendDtmf(char c, ThirdPartyCallSendDtmfCallback callback) {
         // default implementation empty
     }
 
-    IThirdPartyCallProvider getCallback() {
-        return mCallback;
-    }
-
-    private final IThirdPartyCallProvider mCallback = new IThirdPartyCallProvider.Stub() {
+    final IThirdPartyCallProvider callback = new IThirdPartyCallProvider.Stub() {
         @Override
         public void mute(boolean shouldMute) {
             Message.obtain(mHandler, MSG_MUTE, shouldMute ? 1 : 0, 0).sendToTarget();
@@ -80,8 +77,8 @@
         }
 
         @Override
-        public void sendDtmf(char c) {
-            Message.obtain(mHandler, MSG_SEND_DTMF, (int) c, 0).sendToTarget();
+        public void sendDtmf(char c, IThirdPartyCallSendDtmfCallback callback) {
+            Message.obtain(mHandler, MSG_SEND_DTMF, (int) c, 0, callback).sendToTarget();
         }
     };
 
@@ -99,7 +96,9 @@
                     incomingCallAccept();
                     break;
                 case MSG_SEND_DTMF:
-                    sendDtmf((char) msg.arg1);
+                    ThirdPartyCallSendDtmfCallback callback = new ThirdPartyCallSendDtmfCallback(
+                            (IThirdPartyCallSendDtmfCallback) msg.obj);
+                    sendDtmf((char) msg.arg1, callback);
                     break;
             }
         }
diff --git a/telephony/java/android/telephony/ThirdPartyCallSendDtmfCallback.java b/telephony/java/android/telephony/ThirdPartyCallSendDtmfCallback.java
new file mode 100644
index 0000000..5a67cf7
--- /dev/null
+++ b/telephony/java/android/telephony/ThirdPartyCallSendDtmfCallback.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013 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;
+
+import android.os.RemoteException;
+
+import com.android.internal.telephony.IThirdPartyCallSendDtmfCallback;
+
+/**
+ * Callback interface for when DTMF has been sent.
+ */
+public class ThirdPartyCallSendDtmfCallback {
+    private final IThirdPartyCallSendDtmfCallback mCallback;
+
+    public ThirdPartyCallSendDtmfCallback(IThirdPartyCallSendDtmfCallback callback) {
+        if (callback == null) {
+            throw new IllegalArgumentException("Invalid callback");
+        }
+        mCallback = callback;
+    }
+
+    /**
+     * Called by the service when a call provider is available to perform the outgoing or incoming
+     * call.
+     */
+    public void onSendDtmfCompleted() {
+        try {
+            mCallback.onSendDtmfCompleted();
+        } catch (RemoteException e) {
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/ThirdPartyCallService.java b/telephony/java/android/telephony/ThirdPartyCallService.java
index 6eddb43..de6c290 100644
--- a/telephony/java/android/telephony/ThirdPartyCallService.java
+++ b/telephony/java/android/telephony/ThirdPartyCallService.java
@@ -19,6 +19,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
+import android.os.RemoteException;
 import android.util.Pair;
 
 import com.android.internal.telephony.IThirdPartyCallListener;
@@ -39,7 +40,8 @@
     }
 
     /**
-     * Call to attach to an incoming call.
+     * Call to attach to an incoming call. This is in response to a call to {@link
+     * android.telephony.TelephonyManager#newIncomingThirdPartyCall newIncomingThirdPartyCall}.
      */
     public void incomingCallAttach(ThirdPartyCallListener listener, String callId) {
         // default implementation empty
@@ -49,10 +51,10 @@
      * Returns an IBinder instance that can returned from the service's onBind function.
      */
     public IBinder getBinder() {
-        return mCallback;
+        return callback;
     }
 
-    private final IThirdPartyCallService.Stub mCallback = new IThirdPartyCallService.Stub() {
+    private final IThirdPartyCallService.Stub callback = new IThirdPartyCallService.Stub() {
         @Override
         public void outgoingCallInitiate(IThirdPartyCallListener listener, String number) {
             Rlog.w("ThirdPartyPhone", "ThirdPartyCallService.IThirdPartyCallService.out");
diff --git a/telephony/java/com/android/internal/telephony/CallInfo.aidl b/telephony/java/com/android/internal/telephony/CallInfo.aidl
new file mode 100644
index 0000000..9140388
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/CallInfo.aidl
@@ -0,0 +1,19 @@
+/*
+** Copyright 2013, 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 com.android.internal.telephony;
+
+parcelable CallInfo;
diff --git a/telephony/java/com/android/internal/telephony/CallInfo.java b/telephony/java/com/android/internal/telephony/CallInfo.java
new file mode 100644
index 0000000..6bfc9d7
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/CallInfo.java
@@ -0,0 +1,77 @@
+/*
+** Copyright 2013, 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 com.android.internal.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ *  A parcelable holder class of Call information data.
+ */
+public class CallInfo implements Parcelable {
+
+    /**
+     * Endpoint to which the call is connected.
+     * This could be the dialed value for outgoing calls or the caller id of incoming calls.
+     */
+    private String handle;
+
+    public CallInfo(String handle) {
+        this.handle = handle;
+    }
+
+    public String getHandle() {
+        return handle;
+    }
+
+    //
+    // Parcelling related code below here.
+    //
+
+    /**
+     * Responsible for creating CallInfo objects for deserialized Parcels.
+     */
+    public static final Parcelable.Creator<CallInfo> CREATOR
+            = new Parcelable.Creator<CallInfo> () {
+
+        @Override
+        public CallInfo createFromParcel(Parcel source) {
+            return new CallInfo(source.readString());
+        }
+
+        @Override
+        public CallInfo[] newArray(int size) {
+            return new CallInfo[size];
+        }
+    };
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Writes CallInfo object into a serializeable Parcel.
+     */
+    @Override
+    public void writeToParcel(Parcel destination, int flags) {
+        destination.writeString(handle);
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/ICallService.aidl b/telephony/java/com/android/internal/telephony/ICallService.aidl
new file mode 100644
index 0000000..cb9b2e8
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ICallService.aidl
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013 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 com.android.internal.telephony;
+
+import com.android.internal.telephony.ICallServiceAdapter;
+
+/**
+ * Service interface for services which would like to provide calls to be
+ * managed by the system in-call UI.
+ *
+ * This interface provides methods that the android framework can use to deliver commands
+ * for calls provided by this call service including making new calls and disconnecting
+ * existing ones. A binding to ICallService implementations exists for two conditions:
+ * 1) There exists one or more live calls for that call service,
+ * 2) Prior to an outbound call to test if this call service is compatible with the outgoing call.
+ */
+oneway interface ICallService {
+
+    /**
+     * Determines if the CallService can make calls to the handle.
+     * TODO(santoscordon): Move this method into its own service interface long term.
+     * TODO(santoscordon): Add response callback parameter.
+     */
+    void isCompatibleWith(String handle);
+
+    /**
+     * Attempts to call the relevant party using the specified handle, be it a phone number,
+     * SIP address, or some other kind of user ID.  Note that the set of handle types is
+     * dynamically extensible since call providers should be able to implement arbitrary
+     * handle-calling systems.  See {@link #isCompatibleWith}.
+     * TODO(santoscordon): Should this have a response attached to it to ensure that the call
+     * service actually plans to make the call?
+     */
+    void call(String handle);
+
+    /**
+     * Disconnects the call identified by callId.
+     */
+    void disconnect(String callId);
+
+    /**
+     * Sets an implementation of ICallServiceAdapter which the call service can use to add new calls
+     * and communicate state changes of existing calls. This is the first method that is called
+     * after a the framework binds to the call service.
+     */
+    void setCallServiceAdapter(ICallServiceAdapter callServiceAdapter);
+}
diff --git a/telephony/java/com/android/internal/telephony/ICallServiceAdapter.aidl b/telephony/java/com/android/internal/telephony/ICallServiceAdapter.aidl
new file mode 100644
index 0000000..bc900f0
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ICallServiceAdapter.aidl
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013 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 com.android.internal.telephony;
+
+import com.android.internal.telephony.CallInfo;
+
+/**
+ * Provides methods for ICallService implementations to interact with the system phone app.
+ */
+oneway interface ICallServiceAdapter {
+
+    /**
+     * Retrieves a new unique call id for use with newOutgoingCall and newIncomingCall.
+     */
+    void getNextCallId(/* TODO(santoscordon): Needs response object */);
+
+    /**
+     * Tells CallsManager of a new incoming call.
+     */
+    void newIncomingCall(String callId, in CallInfo info);
+
+    /**
+     * Tells CallsManager of a new outgoing call.
+     */
+    void newOutgoingCall(String callId, in CallInfo info);
+
+    /**
+     * Sets a call's state to active (e.g., an ongoing call where two parties can actively
+     * communicate).
+     */
+    void setActive(String callId);
+
+    /**
+     * Sets a call's state to ringing (e.g., an inbound ringing call).
+     */
+    void setRinging(String callId);
+
+    /**
+     * Sets a call's state to dialing (e.g., dialing an outbound call).
+     */
+    void setDialing(String callId);
+
+    /**
+     * Sets a call's state to disconnected.
+     */
+    void setDisconnected(String callId);
+}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 370e27a..3ff5a52 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -17,10 +17,12 @@
 package com.android.internal.telephony;
 
 import android.os.Bundle;
-import java.util.List;
+import android.content.ComponentName;
 import android.telephony.NeighboringCellInfo;
 import android.telephony.CellInfo;
 
+import java.util.List;
+
 /**
  * Interface used to interact with the phone.  Mostly this is used by the
  * TelephonyManager class.  A few places are still using this directly.
@@ -412,4 +414,29 @@
      * @return true on success; false on any failure.
      */
     boolean setRadioMode(int radioMode);
+
+    /**
+     * Inform the phone about a new incoming third party call. The phone will bind to the service
+     * identified by component to handle the call.
+     * @param component the component that should handle the intent.
+     * @param callId the unique id of the call.
+     * @param callerDisplayName the name shown to the user. Normally this will be the caller's phone
+     *                          number.
+     */
+    void newIncomingThirdPartyCall(in ComponentName component, String callId,
+            String callerDisplayName);
+
+    /**
+     * Obtain the current state of Wi-Fi calling.
+     *
+     * @see android.telephony.TelephonyManager.WifiCallingChoices
+     */
+    int getWhenToMakeWifiCalls();
+
+    /**
+     * Set the current state of Wi-Fi calling.
+     *
+     * @see android.telephony.TelephonyManager.WifiCallingChoices
+     */
+    void setWhenToMakeWifiCalls(int state);
 }
diff --git a/telephony/java/com/android/internal/telephony/IThirdPartyCallProvider.aidl b/telephony/java/com/android/internal/telephony/IThirdPartyCallProvider.aidl
index a9d67a4..9d595b0 100644
--- a/telephony/java/com/android/internal/telephony/IThirdPartyCallProvider.aidl
+++ b/telephony/java/com/android/internal/telephony/IThirdPartyCallProvider.aidl
@@ -17,6 +17,7 @@
 package com.android.internal.telephony;
 
 import com.android.internal.telephony.IThirdPartyCallListener;
+import com.android.internal.telephony.IThirdPartyCallSendDtmfCallback;
 
 /**
  * Interface sent to ThirdPartyCallListener.onCallProviderAttached. This is used to control an
@@ -42,5 +43,5 @@
     /**
      * Sends the given DTMF code. The code can be '0'-'9', 'A'-'D', '#', or '*'.
      */
-    void sendDtmf(char c);
+    void sendDtmf(char c, IThirdPartyCallSendDtmfCallback callback);
 }
diff --git a/telephony/java/com/android/internal/telephony/IThirdPartyCallSendDtmfCallback.aidl b/telephony/java/com/android/internal/telephony/IThirdPartyCallSendDtmfCallback.aidl
new file mode 100644
index 0000000..3a02b06
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IThirdPartyCallSendDtmfCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2013 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 com.android.internal.telephony;
+
+/**
+ * Callback interface for when DTMF has been sent.
+ */
+oneway interface IThirdPartyCallSendDtmfCallback {
+    /**
+     * Called when the DTMF code has been sent.
+     */
+    void onSendDtmfCompleted();
+}
diff --git a/telephony/java/com/android/internal/telephony/IThirdPartyCallService.aidl b/telephony/java/com/android/internal/telephony/IThirdPartyCallService.aidl
index c9ee4ed..597567a 100644
--- a/telephony/java/com/android/internal/telephony/IThirdPartyCallService.aidl
+++ b/telephony/java/com/android/internal/telephony/IThirdPartyCallService.aidl
@@ -28,7 +28,8 @@
     void outgoingCallInitiate(IThirdPartyCallListener listener, String number);
 
     /**
-     * Call to attach to an incoming call.
+     * Call to attach to an incoming call. This is in response to a call to
+     * TelephonyManager.newIncomingThirdPartyCall.
      */
     void incomingCallAttach(IThirdPartyCallListener listener, String callId);
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index fc6c997..ade024f 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -57,6 +57,7 @@
     public static final int PHONE_TYPE_GSM = RILConstants.GSM_PHONE;
     public static final int PHONE_TYPE_CDMA = RILConstants.CDMA_PHONE;
     public static final int PHONE_TYPE_SIP = RILConstants.SIP_PHONE;
+    public static final int PHONE_TYPE_THIRD_PARTY = RILConstants.THIRD_PARTY_PHONE;
 
     // Modes for LTE_ON_CDMA
     public static final int LTE_ON_CDMA_UNKNOWN = RILConstants.LTE_ON_CDMA_UNKNOWN;
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 6015df0..b8b90ee 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -84,6 +84,7 @@
     int GSM_PHONE = 1;
     int CDMA_PHONE = 2;
     int SIP_PHONE  = 3;
+    int THIRD_PARTY_PHONE = 4;
 
     int LTE_ON_CDMA_UNKNOWN = -1;
     int LTE_ON_CDMA_FALSE = 0;