am 3cb2d3be: am 1862af57: Merge "SipService: supply PendingIntent when open a profile." into gingerbread

Merge commit '3cb2d3be6cb501c77c7a5765d954363125857cca'

* commit '3cb2d3be6cb501c77c7a5765d954363125857cca':
  SipService: supply PendingIntent when open a profile.
diff --git a/voip/java/android/net/sip/ISipService.aidl b/voip/java/android/net/sip/ISipService.aidl
index 6c68213..3250bf9 100644
--- a/voip/java/android/net/sip/ISipService.aidl
+++ b/voip/java/android/net/sip/ISipService.aidl
@@ -16,6 +16,7 @@
 
 package android.net.sip;
 
+import android.app.PendingIntent;
 import android.net.sip.ISipSession;
 import android.net.sip.ISipSessionListener;
 import android.net.sip.SipProfile;
@@ -26,7 +27,7 @@
 interface ISipService {
     void open(in SipProfile localProfile);
     void open3(in SipProfile localProfile,
-            String incomingCallBroadcastAction,
+            in PendingIntent incomingCallPendingIntent,
             in ISipSessionListener listener);
     void close(in String localProfileUri);
     boolean isOpened(String localProfileUri);
diff --git a/voip/java/android/net/sip/SipManager.java b/voip/java/android/net/sip/SipManager.java
index bd859e8..80c35fb 100644
--- a/voip/java/android/net/sip/SipManager.java
+++ b/voip/java/android/net/sip/SipManager.java
@@ -16,6 +16,7 @@
 
 package android.net.sip;
 
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -34,7 +35,7 @@
  * <li>open a {@link SipProfile} to get ready for making outbound calls or have
  *      the background SIP service listen to incoming calls and broadcast them
  *      with registered command string. See
- *      {@link #open(SipProfile, String, SipRegistrationListener)},
+ *      {@link #open(SipProfile, PendingIntent, SipRegistrationListener)},
  *      {@link #open(SipProfile)}, {@link #close}, {@link #isOpened} and
  *      {@link #isRegistered}. It also facilitates handling of the incoming call
  *      broadcast intent. See
@@ -51,6 +52,19 @@
  */
 public class SipManager {
     /**
+     * The result code to be sent back with the incoming call
+     * {@link PendingIntent}.
+     * @see #open(SipProfile, PendingIntent, SipRegistrationListener)
+     */
+    public static final int INCOMING_CALL_RESULT_CODE = 101;
+
+    /** Part of the incoming call intent. */
+    public static final String EXTRA_CALL_ID = "android:sipCallID";
+
+    /** Part of the incoming call intent. */
+    public static final String EXTRA_OFFER_SD = "android:sipOfferSD";
+
+    /**
      * Action string for the incoming call intent for the Phone app.
      * Internal use only.
      * @hide
@@ -78,12 +92,6 @@
      */
     public static final String EXTRA_LOCAL_URI = "android:localSipUri";
 
-    /** Part of the incoming call intent. */
-    public static final String EXTRA_CALL_ID = "android:sipCallID";
-
-    /** Part of the incoming call intent. */
-    public static final String EXTRA_OFFER_SD = "android:sipOfferSD";
-
     private static final String TAG = "SipManager";
 
     private ISipService mSipService;
@@ -142,7 +150,8 @@
     /**
      * Opens the profile for making calls. The caller may make subsequent calls
      * through {@link #makeAudioCall}. If one also wants to receive calls on the
-     * profile, use {@link #open(SipProfile, String, SipRegistrationListener)}
+     * profile, use
+     * {@link #open(SipProfile, PendingIntent, SipRegistrationListener)}
      * instead.
      *
      * @param localProfile the SIP profile to make calls from
@@ -165,17 +174,29 @@
      * in order to receive calls from the provider.
      *
      * @param localProfile the SIP profile to receive incoming calls for
-     * @param incomingCallBroadcastAction the action to be broadcast when an
-     *      incoming call is received
+     * @param incomingCallPendingIntent When an incoming call is received, the
+     *      SIP service will call
+     *      {@link PendingIntent#send(Context, int, Intent)} to send back the
+     *      intent to the caller with {@link #INCOMING_CALL_RESULT_CODE} as the
+     *      result code and the intent to fill in the call ID and session
+     *      description information. It cannot be null.
      * @param listener to listen to registration events; can be null
+     * @see #getCallId
+     * @see #getOfferSessionDescription
+     * @see #takeAudioCall
+     * @throws NullPointerException if {@code incomingCallPendingIntent} is null
      * @throws SipException if the profile contains incorrect settings or
      *      calling the SIP service results in an error
      */
     public void open(SipProfile localProfile,
-            String incomingCallBroadcastAction,
+            PendingIntent incomingCallPendingIntent,
             SipRegistrationListener listener) throws SipException {
+        if (incomingCallPendingIntent == null) {
+            throw new NullPointerException(
+                    "incomingCallPendingIntent cannot be null");
+        }
         try {
-            mSipService.open3(localProfile, incomingCallBroadcastAction,
+            mSipService.open3(localProfile, incomingCallPendingIntent,
                     createRelay(listener, localProfile.getUriString()));
         } catch (RemoteException e) {
             throw new SipException("open()", e);
@@ -184,7 +205,8 @@
 
     /**
      * Sets the listener to listen to registration events. No effect if the
-     * profile has not been opened to receive calls (see {@link #open}).
+     * profile has not been opened to receive calls (see
+     * {@link #open(SipProfile, PendingIntent, SipRegistrationListener)}).
      *
      * @param localProfileUri the URI of the profile
      * @param listener to listen to registration events; can be null
@@ -282,9 +304,9 @@
     }
 
     /**
-     * Creates a {@link SipAudioCall} to make a call. To use this method, one
-     * must call {@link #open(SipProfile)} first. The attempt will be timed out
-     * if the call is not established within {@code timeout} seconds and
+     * Creates a {@link SipAudioCall} to make an audio call. The attempt will be
+     * timed out if the call is not established within {@code timeout} seconds
+     * and
      * {@code SipAudioCall.Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
      * will be called.
      *
@@ -416,9 +438,11 @@
 
     /**
      * Manually registers the profile to the corresponding SIP provider for
-     * receiving calls. {@link #open(SipProfile, String, SipRegistrationListener)}
-     * is still needed to be called at least once in order for the SIP service
-     * to broadcast an intent when an incoming call is received.
+     * receiving calls.
+     * {@link #open(SipProfile, PendingIntent, SipRegistrationListener)} is
+     * still needed to be called at least once in order for the SIP service to
+     * notify the caller with the {@code PendingIntent} when an incoming call is
+     * received.
      *
      * @param localProfile the SIP profile to register with
      * @param expiryTime registration expiration time (in seconds)
diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java
index 405dff8..a7c61e5 100644
--- a/voip/java/com/android/server/sip/SipService.java
+++ b/voip/java/com/android/server/sip/SipService.java
@@ -134,14 +134,6 @@
 
     public void open(SipProfile localProfile) {
         localProfile.setCallingUid(Binder.getCallingUid());
-        if (localProfile.getAutoRegistration() && isCallerRadio()) {
-            openToReceiveCalls(localProfile);
-        } else {
-            openToMakeCalls(localProfile);
-        }
-    }
-
-    private void openToMakeCalls(SipProfile localProfile) {
         try {
             createGroup(localProfile);
         } catch (SipException e) {
@@ -150,28 +142,20 @@
         }
     }
 
-    private void openToReceiveCalls(SipProfile localProfile) {
-        open3(localProfile, SipManager.ACTION_SIP_INCOMING_CALL, null);
-    }
-
     public synchronized void open3(SipProfile localProfile,
-            String incomingCallBroadcastAction, ISipSessionListener listener) {
+            PendingIntent incomingCallPendingIntent,
+            ISipSessionListener listener) {
         localProfile.setCallingUid(Binder.getCallingUid());
-        if (TextUtils.isEmpty(incomingCallBroadcastAction)) {
-            Log.w(TAG, "empty broadcast action for incoming call");
-            return;
-        }
-        if (incomingCallBroadcastAction.equals(
-                SipManager.ACTION_SIP_INCOMING_CALL) && !isCallerRadio()) {
-            Log.w(TAG, "failed to open the profile; "
-                    + "the action string is reserved");
+        if (incomingCallPendingIntent == null) {
+            Log.w(TAG, "incomingCallPendingIntent cannot be null; "
+                    + "the profile is not opened");
             return;
         }
         if (DEBUG) Log.d(TAG, "open3: " + localProfile.getUriString() + ": "
-                + incomingCallBroadcastAction + ": " + listener);
+                + incomingCallPendingIntent + ": " + listener);
         try {
             SipSessionGroupExt group = createGroup(localProfile,
-                    incomingCallBroadcastAction, listener);
+                    incomingCallPendingIntent, listener);
             if (localProfile.getAutoRegistration()) {
                 group.openToReceiveCalls();
                 if (isWifiOn()) grabWifiLock();
@@ -287,20 +271,19 @@
     }
 
     private SipSessionGroupExt createGroup(SipProfile localProfile,
-            String incomingCallBroadcastAction, ISipSessionListener listener)
-            throws SipException {
+            PendingIntent incomingCallPendingIntent,
+            ISipSessionListener listener) throws SipException {
         String key = localProfile.getUriString();
         SipSessionGroupExt group = mSipGroups.get(key);
         if (group != null) {
             if (!isCallerCreator(group)) {
                 throw new SipException("only creator can access the profile");
             }
-            group.setIncomingCallBroadcastAction(
-                    incomingCallBroadcastAction);
+            group.setIncomingCallPendingIntent(incomingCallPendingIntent);
             group.setListener(listener);
         } else {
             group = new SipSessionGroupExt(localProfile,
-                    incomingCallBroadcastAction, listener);
+                    incomingCallPendingIntent, listener);
             mSipGroups.put(key, group);
             notifyProfileAdded(localProfile);
         }
@@ -405,19 +388,19 @@
 
     private class SipSessionGroupExt extends SipSessionAdapter {
         private SipSessionGroup mSipGroup;
-        private String mIncomingCallBroadcastAction;
+        private PendingIntent mIncomingCallPendingIntent;
         private boolean mOpened;
 
         private AutoRegistrationProcess mAutoRegistration =
                 new AutoRegistrationProcess();
 
         public SipSessionGroupExt(SipProfile localProfile,
-                String incomingCallBroadcastAction,
+                PendingIntent incomingCallPendingIntent,
                 ISipSessionListener listener) throws SipException {
             String password = localProfile.getPassword();
             SipProfile p = duplicate(localProfile);
             mSipGroup = createSipSessionGroup(mLocalIp, p, password);
-            mIncomingCallBroadcastAction = incomingCallBroadcastAction;
+            mIncomingCallPendingIntent = incomingCallPendingIntent;
             mAutoRegistration.setListener(listener);
         }
 
@@ -458,8 +441,8 @@
             mAutoRegistration.setListener(listener);
         }
 
-        public void setIncomingCallBroadcastAction(String action) {
-            mIncomingCallBroadcastAction = action;
+        public void setIncomingCallPendingIntent(PendingIntent pIntent) {
+            mIncomingCallPendingIntent = pIntent;
         }
 
         public void openToReceiveCalls() throws SipException {
@@ -469,7 +452,7 @@
                 mAutoRegistration.start(mSipGroup);
             }
             if (DEBUG) Log.d(TAG, "  openToReceiveCalls: " + getUri() + ": "
-                    + mIncomingCallBroadcastAction);
+                    + mIncomingCallPendingIntent);
         }
 
         public void onConnectivityChanged(boolean connected)
@@ -481,7 +464,7 @@
             } else {
                 // close mSipGroup but remember mOpened
                 if (DEBUG) Log.d(TAG, "  close auto reg temporarily: "
-                        + getUri() + ": " + mIncomingCallBroadcastAction);
+                        + getUri() + ": " + mIncomingCallPendingIntent);
                 mSipGroup.close();
                 mAutoRegistration.stop();
             }
@@ -508,7 +491,7 @@
             mSipGroup.close();
             mAutoRegistration.stop();
             if (DEBUG) Log.d(TAG, "   close: " + getUri() + ": "
-                    + mIncomingCallBroadcastAction);
+                    + mIncomingCallPendingIntent);
         }
 
         public ISipSession createSession(ISipSessionListener listener) {
@@ -516,8 +499,10 @@
         }
 
         @Override
-        public void onRinging(ISipSession session, SipProfile caller,
+        public void onRinging(ISipSession s, SipProfile caller,
                 String sessionDescription) {
+            SipSessionGroup.SipSessionImpl session =
+                    (SipSessionGroup.SipSessionImpl) s;
             synchronized (SipService.this) {
                 try {
                     if (!isRegistered()) {
@@ -528,15 +513,15 @@
                     // send out incoming call broadcast
                     addPendingSession(session);
                     Intent intent = SipManager.createIncomingCallBroadcast(
-                            session.getCallId(), sessionDescription)
-                            .setAction(mIncomingCallBroadcastAction);
+                            session.getCallId(), sessionDescription);
                     if (DEBUG) Log.d(TAG, " ringing~~ " + getUri() + ": "
                             + caller.getUri() + ": " + session.getCallId()
-                            + " " + mIncomingCallBroadcastAction);
-                    mContext.sendBroadcast(intent);
-                } catch (RemoteException e) {
-                    // should never happen with a local call
-                    Log.e(TAG, "processCall()", e);
+                            + " " + mIncomingCallPendingIntent);
+                    mIncomingCallPendingIntent.send(mContext,
+                            SipManager.INCOMING_CALL_RESULT_CODE, intent);
+                } catch (PendingIntent.CanceledException e) {
+                    Log.w(TAG, "pendingIntent is canceled, drop incoming call");
+                    session.endCall();
                 }
             }
         }