Add ThirdPartyCall APIs to master

These are APIs for the new ThirdPartyPhone feature.

Note, these APIs can't actually be used yet on master for two reasons:
  - initiating a call from a 3rd party app isn't possible yet because
    the TelephonyManager APIs aren't being added to master.
  - the TeleService implementation of these APIs aren't being added to
    master.

Also, these APIs will be removed and the final ones will be added
once they're ready to be merged into master.

Change-Id: Ie783290451da448a011f813983e55b12047b5d99
diff --git a/Android.mk b/Android.mk
index b9035ff..8b137ea 100644
--- a/Android.mk
+++ b/Android.mk
@@ -268,6 +268,9 @@
 	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/IThirdPartyCallService.aidl \
 	telephony/java/com/android/internal/telephony/ISms.aidl \
 	telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
 	telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
diff --git a/api/current.txt b/api/current.txt
index 7e757b5..c7fe3ba 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -24135,6 +24135,32 @@
     field public static final int SIM_STATE_UNKNOWN = 0; // 0x0
   }
 
+  public class ThirdPartyCallListener {
+    ctor public ThirdPartyCallListener(com.android.internal.telephony.IThirdPartyCallListener);
+    method public void onCallEnded(int);
+    method public void onCallEstablished();
+    method public void onCallProviderAttached(android.telephony.ThirdPartyCallProvider);
+    method public void onRingingStarted();
+    field public static final int CALL_END_INCOMING_MISSED = 2; // 0x2
+    field public static final int CALL_END_NORMAL = 1; // 0x1
+    field public static final int CALL_END_OTHER = 3; // 0x3
+  }
+
+  public class ThirdPartyCallProvider {
+    ctor public ThirdPartyCallProvider();
+    method public void hangup();
+    method public void incomingCallAccept();
+    method public void mute(boolean);
+    method public void sendDtmf(char);
+  }
+
+  public class ThirdPartyCallService {
+    ctor public ThirdPartyCallService();
+    method public android.os.IBinder getBinder();
+    method public void incomingCallAttach(android.telephony.ThirdPartyCallListener, java.lang.String);
+    method public void outgoingCallInitiate(android.telephony.ThirdPartyCallListener, java.lang.String);
+  }
+
 }
 
 package android.telephony.cdma {
@@ -33535,6 +33561,24 @@
 
 }
 
+package com.android.internal.telephony {
+
+  public abstract interface IThirdPartyCallListener implements android.os.IInterface {
+    method public abstract void onCallEnded(int) throws android.os.RemoteException;
+    method public abstract void onCallEstablished() throws android.os.RemoteException;
+    method public abstract void onCallProviderAttached(com.android.internal.telephony.IThirdPartyCallProvider) throws android.os.RemoteException;
+    method public abstract void onRingingStarted() throws android.os.RemoteException;
+  }
+
+  public abstract interface IThirdPartyCallProvider implements android.os.IInterface {
+    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;
+  }
+
+}
+
 package com.android.internal.util {
 
   public abstract interface Predicate {
diff --git a/telephony/java/android/telephony/ThirdPartyCallListener.java b/telephony/java/android/telephony/ThirdPartyCallListener.java
new file mode 100644
index 0000000..81bbf6c
--- /dev/null
+++ b/telephony/java/android/telephony/ThirdPartyCallListener.java
@@ -0,0 +1,84 @@
+/*
+ * 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.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+
+import com.android.internal.telephony.IThirdPartyCallListener;
+
+/**
+ * Interface provided to {@link android.telephony.ThirdPartyCallService}. The service can use this
+ * to notify the listener of changes to the call state.
+ */
+public class ThirdPartyCallListener {
+    private final IThirdPartyCallListener mListener;
+
+    // Call end reason. TODO: rename this to DisconnectCause once they are public.
+    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;
+    }
+
+    /**
+     * Called by the service when a call provider is available to perform the outgoing or incoming
+     * call.
+     */
+    public void onCallProviderAttached(ThirdPartyCallProvider callProvider) {
+        try {
+            mListener.onCallProviderAttached(callProvider.getCallback());
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Notifies the listener that ringing has started for this call.
+     */
+    public void onRingingStarted() {
+        try {
+            mListener.onRingingStarted();
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Notifies the listener that the call has been successfully established.
+     */
+    public void onCallEstablished() {
+        try {
+            mListener.onCallEstablished();
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Notifies the listener that the call has ended.
+     */
+    public void onCallEnded(int reason) {
+        try {
+            mListener.onCallEnded(reason);
+        } catch (RemoteException e) {
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/ThirdPartyCallProvider.java b/telephony/java/android/telephony/ThirdPartyCallProvider.java
new file mode 100644
index 0000000..bd8a1ea
--- /dev/null
+++ b/telephony/java/android/telephony/ThirdPartyCallProvider.java
@@ -0,0 +1,107 @@
+/*
+ * 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.Handler;
+import android.os.Message;
+
+import com.android.internal.telephony.IThirdPartyCallProvider;
+
+/**
+ * Interface sent to {@link android.telephony.ThirdPartyCallListener#onCallProviderAttached
+ * onCallProviderAttached}. This is used to control an outgoing or an incoming call.
+ */
+public class ThirdPartyCallProvider {
+    private static final int MSG_MUTE = 1;
+    private static final int MSG_HANGUP = 2;
+    private static final int MSG_INCOMING_CALL_ACCEPT = 3;
+    private static final int MSG_SEND_DTMF = 4;
+
+    /**
+     * Mutes or unmutes the call.
+     */
+    public void mute(boolean shouldMute) {
+        // default implementation empty
+    }
+
+    /**
+     * Ends the current call. If this is an unanswered incoming call then the call is rejected.
+     */
+    public void hangup() {
+        // default implementation empty
+    }
+
+   /**
+     * Accepts the incoming call.
+     */
+    public void incomingCallAccept() {
+        // default implementation empty
+    }
+
+    /**
+     * Sends the given DTMF code. The code can be '0'-'9', 'A'-'D', '#', or '*'.
+     */
+    public void sendDtmf(char c) {
+        // default implementation empty
+    }
+
+    IThirdPartyCallProvider getCallback() {
+        return mCallback;
+    }
+
+    private final IThirdPartyCallProvider mCallback = new IThirdPartyCallProvider.Stub() {
+        @Override
+        public void mute(boolean shouldMute) {
+            Message.obtain(mHandler, MSG_MUTE, shouldMute ? 1 : 0, 0).sendToTarget();
+        }
+
+        @Override
+        public void hangup() {
+            Message.obtain(mHandler, MSG_HANGUP).sendToTarget();
+        }
+
+        @Override
+        public void incomingCallAccept() {
+            Message.obtain(mHandler, MSG_INCOMING_CALL_ACCEPT).sendToTarget();
+        }
+
+        @Override
+        public void sendDtmf(char c) {
+            Message.obtain(mHandler, MSG_SEND_DTMF, (int) c, 0).sendToTarget();
+        }
+    };
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_MUTE:
+                    mute(msg.arg1 != 0);
+                    break;
+                case MSG_HANGUP:
+                    hangup();
+                    break;
+                case MSG_INCOMING_CALL_ACCEPT:
+                    incomingCallAccept();
+                    break;
+                case MSG_SEND_DTMF:
+                    sendDtmf((char) msg.arg1);
+                    break;
+            }
+        }
+    };
+}
diff --git a/telephony/java/android/telephony/ThirdPartyCallService.java b/telephony/java/android/telephony/ThirdPartyCallService.java
new file mode 100644
index 0000000..e82820f
--- /dev/null
+++ b/telephony/java/android/telephony/ThirdPartyCallService.java
@@ -0,0 +1,95 @@
+/*
+ * 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.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Pair;
+
+import com.android.internal.telephony.IThirdPartyCallListener;
+import com.android.internal.telephony.IThirdPartyCallService;
+
+/**
+ * Interface provided by a service to start outgoing calls and attach to incoming calls.
+ */
+public class ThirdPartyCallService {
+    private static final int MSG_OUTGOING_CALL_INITIATE = 1;
+    private static final int MSG_INCOMING_CALL_ATTACH = 2;
+
+    /**
+     * Call to start a new outgoing call.
+     */
+    public void outgoingCallInitiate(ThirdPartyCallListener listener, String number) {
+        // default implementation empty
+    }
+
+    /**
+     * Call to attach to an incoming call.
+     */
+    public void incomingCallAttach(ThirdPartyCallListener listener, String callId) {
+        // default implementation empty
+    }
+
+    /**
+     * Returns an IBinder instance that can returned from the service's onBind function.
+     */
+    public IBinder getBinder() {
+        return mCallback;
+    }
+
+    private final IThirdPartyCallService.Stub mCallback = new IThirdPartyCallService.Stub() {
+        @Override
+        public void outgoingCallInitiate(IThirdPartyCallListener listener, String number) {
+            Rlog.w("ThirdPartyPhone", "ThirdPartyCallService.IThirdPartyCallService.out");
+            Message.obtain(mHandler, MSG_OUTGOING_CALL_INITIATE,
+                    Pair.create(listener, number)).sendToTarget();
+        }
+
+        @Override
+        public void incomingCallAttach(IThirdPartyCallListener listener, String callId) {
+            Rlog.w("ThirdPartyPhone", "ThirdPartyCallService.IThirdPartyCallService.in");
+            Message.obtain(mHandler, MSG_INCOMING_CALL_ATTACH,
+                    Pair.create(listener, callId)).sendToTarget();
+        }
+    };
+
+    private final Handler mHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            Rlog.w("ThirdPartyPhone", "ThirdPartyCallService.handleMessage: " + msg.what);
+            switch (msg.what) {
+                case MSG_OUTGOING_CALL_INITIATE: {
+                    Rlog.w("ThirdPartyPhone", "ThirdPartyCallService.handleMessage out");
+                    Pair<IThirdPartyCallListener, String> pair =
+                            (Pair<IThirdPartyCallListener, String>) msg.obj;
+                    ThirdPartyCallListener listener = new ThirdPartyCallListener(pair.first);
+                    outgoingCallInitiate(listener, pair.second);
+                    break;
+                }
+                case MSG_INCOMING_CALL_ATTACH: {
+                    Rlog.w("ThirdPartyPhone", "ThirdPartyCallService.handleMessage in");
+                    Pair<IThirdPartyCallListener, String> pair =
+                            (Pair<IThirdPartyCallListener, String>) msg.obj;
+                    ThirdPartyCallListener listener = new ThirdPartyCallListener(pair.first);
+                    incomingCallAttach(listener, pair.second);
+                    break;
+                }
+            }
+        }
+    };
+}
diff --git a/telephony/java/com/android/internal/telephony/IThirdPartyCallListener.aidl b/telephony/java/com/android/internal/telephony/IThirdPartyCallListener.aidl
new file mode 100644
index 0000000..bcf2d81
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IThirdPartyCallListener.aidl
@@ -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 com.android.internal.telephony;
+
+import com.android.internal.telephony.IThirdPartyCallProvider;
+
+/**
+ * Interface provided to ThirdPartyCallService. The service can use this to notify the listener of
+ * changes to the call state.
+ */
+oneway interface IThirdPartyCallListener {
+    /**
+     * Called by the service when a call provider is available to perform the outgoing or incoming
+     * call.
+     */
+    void onCallProviderAttached(IThirdPartyCallProvider callProvider);
+
+    /**
+     * Notifies the listener that ringing has started for this call.
+     */
+    void onRingingStarted();
+
+    /**
+     * Notifies the listener that the call has been successfully established.
+     */
+    void onCallEstablished();
+
+    /**
+     * Notifies the listener that the call has ended.
+     */
+    void onCallEnded(int reason);
+}
diff --git a/telephony/java/com/android/internal/telephony/IThirdPartyCallProvider.aidl b/telephony/java/com/android/internal/telephony/IThirdPartyCallProvider.aidl
new file mode 100644
index 0000000..a9d67a4
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IThirdPartyCallProvider.aidl
@@ -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 com.android.internal.telephony;
+
+import com.android.internal.telephony.IThirdPartyCallListener;
+
+/**
+ * Interface sent to ThirdPartyCallListener.onCallProviderAttached. This is used to control an
+ * outgoing or incoming call.
+ */
+oneway interface IThirdPartyCallProvider {
+    /**
+     * Mutes or unmutes the call.
+     */
+    void mute(boolean shouldMute);
+
+    /**
+     * Ends the current call. If this is an unanswered incoming call then the call is rejected (for
+     * example, a notification is sent to a server that the user declined the call).
+     */
+    void hangup();
+
+    /**
+     * Accepts the incoming call.
+     */
+    void incomingCallAccept();
+
+    /**
+     * Sends the given DTMF code. The code can be '0'-'9', 'A'-'D', '#', or '*'.
+     */
+    void sendDtmf(char c);
+}
diff --git a/telephony/java/com/android/internal/telephony/IThirdPartyCallService.aidl b/telephony/java/com/android/internal/telephony/IThirdPartyCallService.aidl
new file mode 100644
index 0000000..c9ee4ed
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IThirdPartyCallService.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.IThirdPartyCallListener;
+
+/**
+ * Interface provided by a service to start outgoing calls and attach to incoming calls.
+ */
+oneway interface IThirdPartyCallService {
+    /**
+     * Call to start a new outgoing call.
+     */
+    void outgoingCallInitiate(IThirdPartyCallListener listener, String number);
+
+    /**
+     * Call to attach to an incoming call.
+     */
+    void incomingCallAttach(IThirdPartyCallListener listener, String callId);
+}