198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang/* 298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Copyright (C) 2010 The Android Open Source Project 398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Licensed under the Apache License, Version 2.0 (the "License"); 598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * you may not use this file except in compliance with the License. 698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * You may obtain a copy of the License at 798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * http://www.apache.org/licenses/LICENSE-2.0 998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 1098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Unless required by applicable law or agreed to in writing, software 1198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * distributed under the License is distributed on an "AS IS" BASIS, 1298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * See the License for the specific language governing permissions and 1498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * limitations under the License. 1598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 1698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 1798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangpackage android.net.sip; 1898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 19845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyanimport android.app.PendingIntent; 2098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport android.content.Context; 2198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport android.content.Intent; 2269d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyanimport android.content.pm.PackageManager; 2398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport android.os.IBinder; 2498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport android.os.RemoteException; 2598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport android.os.ServiceManager; 269329db04f13480ccdff013dcc00cdb96f12a921cWink Savilleimport android.telephony.Rlog; 2798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 2898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport java.text.ParseException; 2998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 3098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang/** 3116b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * Provides APIs for SIP tasks, such as initiating SIP connections, and provides access to related 3216b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * SIP services. This class is the starting point for any SIP actions. You can acquire an instance 3316b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * of it with {@link #newInstance newInstance()}.</p> 3416b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * <p>The APIs in this class allows you to:</p> 3598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * <ul> 3616b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * <li>Create a {@link SipSession} to get ready for making calls or listen for incoming calls. See 3716b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * {@link #createSipSession createSipSession()} and {@link #getSessionFor getSessionFor()}.</li> 3816b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * <li>Initiate and receive generic SIP calls or audio-only SIP calls. Generic SIP calls may 3916b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * be video, audio, or other, and are initiated with {@link #open open()}. Audio-only SIP calls 4016b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * should be handled with a {@link SipAudioCall}, which you can acquire with {@link 4116b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * #makeAudioCall makeAudioCall()} and {@link #takeAudioCall takeAudioCall()}.</li> 4216b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * <li>Register and unregister with a SIP service provider, with 4316b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * {@link #register register()} and {@link #unregister unregister()}.</li> 4416b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * <li>Verify session connectivity, with {@link #isOpened isOpened()} and 4516b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * {@link #isRegistered isRegistered()}.</li> 4698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * </ul> 4716b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * <p class="note"><strong>Note:</strong> Not all Android-powered devices support VOIP calls using 4816b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * SIP. You should always call {@link android.net.sip.SipManager#isVoipSupported 4916b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * isVoipSupported()} to verify that the device supports VOIP calling and {@link 5016b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * android.net.sip.SipManager#isApiSupported isApiSupported()} to verify that the device supports 51b4074803f775e5a4616287804f3405fd17eecab3Joe Fernandez * the SIP APIs. Your application must also request the {@link 5216b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * android.Manifest.permission#INTERNET} and {@link android.Manifest.permission#USE_SIP} 5316b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * permissions.</p> 54b4074803f775e5a4616287804f3405fd17eecab3Joe Fernandez * 55b4074803f775e5a4616287804f3405fd17eecab3Joe Fernandez * <div class="special reference"> 56b4074803f775e5a4616287804f3405fd17eecab3Joe Fernandez * <h3>Developer Guides</h3> 57b4074803f775e5a4616287804f3405fd17eecab3Joe Fernandez * <p>For more information about using SIP, read the 58b4074803f775e5a4616287804f3405fd17eecab3Joe Fernandez * <a href="{@docRoot}guide/topics/network/sip.html">Session Initiation Protocol</a> 59b4074803f775e5a4616287804f3405fd17eecab3Joe Fernandez * developer guide.</p> 60b4074803f775e5a4616287804f3405fd17eecab3Joe Fernandez * </div> 6198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 6298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangpublic class SipManager { 633adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan /** 64845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * The result code to be sent back with the incoming call 65845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * {@link PendingIntent}. 66845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * @see #open(SipProfile, PendingIntent, SipRegistrationListener) 67845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan */ 68845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan public static final int INCOMING_CALL_RESULT_CODE = 101; 69845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan 704e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan /** 714e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * Key to retrieve the call ID from an incoming call intent. 724e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * @see #open(SipProfile, PendingIntent, SipRegistrationListener) 734e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan */ 74845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan public static final String EXTRA_CALL_ID = "android:sipCallID"; 75845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan 764e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan /** 774e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * Key to retrieve the offered session description from an incoming call 784e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * intent. 794e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * @see #open(SipProfile, PendingIntent, SipRegistrationListener) 804e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan */ 81845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan public static final String EXTRA_OFFER_SD = "android:sipOfferSD"; 82845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan 83845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan /** 8422523a59d879cf47f1e9c202d001d569fad4f69eHung-ying Tyan * Action to broadcast when SipService is up. 8522523a59d879cf47f1e9c202d001d569fad4f69eHung-ying Tyan * Internal use only. 8622523a59d879cf47f1e9c202d001d569fad4f69eHung-ying Tyan * @hide 8722523a59d879cf47f1e9c202d001d569fad4f69eHung-ying Tyan */ 8822523a59d879cf47f1e9c202d001d569fad4f69eHung-ying Tyan public static final String ACTION_SIP_SERVICE_UP = 8922523a59d879cf47f1e9c202d001d569fad4f69eHung-ying Tyan "android.net.sip.SIP_SERVICE_UP"; 9022523a59d879cf47f1e9c202d001d569fad4f69eHung-ying Tyan /** 913adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * Action string for the incoming call intent for the Phone app. 923adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * Internal use only. 933adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * @hide 943adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan */ 953adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan public static final String ACTION_SIP_INCOMING_CALL = 9698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang "com.android.phone.SIP_INCOMING_CALL"; 973adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan /** 983adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * Action string for the add-phone intent. 993adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * Internal use only. 1003adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * @hide 1013adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan */ 1023adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan public static final String ACTION_SIP_ADD_PHONE = 10398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang "com.android.phone.SIP_ADD_PHONE"; 1043adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan /** 1053adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * Action string for the remove-phone intent. 1063adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * Internal use only. 1073adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * @hide 1083adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan */ 1093adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan public static final String ACTION_SIP_REMOVE_PHONE = 11098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang "com.android.phone.SIP_REMOVE_PHONE"; 111cf38b8464007ebf626fc0d61a646491fc3d794cdTyler Gunn 112cf38b8464007ebf626fc0d61a646491fc3d794cdTyler Gunn /** 113cf38b8464007ebf626fc0d61a646491fc3d794cdTyler Gunn * Action string for the SIP call option configuration changed intent. 114cf38b8464007ebf626fc0d61a646491fc3d794cdTyler Gunn * This is used to communicate change to the SIP call option, triggering re-registration of 115cf38b8464007ebf626fc0d61a646491fc3d794cdTyler Gunn * the SIP phone accounts. 116cf38b8464007ebf626fc0d61a646491fc3d794cdTyler Gunn * Internal use only. 117cf38b8464007ebf626fc0d61a646491fc3d794cdTyler Gunn * @hide 118cf38b8464007ebf626fc0d61a646491fc3d794cdTyler Gunn */ 119cf38b8464007ebf626fc0d61a646491fc3d794cdTyler Gunn public static final String ACTION_SIP_CALL_OPTION_CHANGED = 120cf38b8464007ebf626fc0d61a646491fc3d794cdTyler Gunn "com.android.phone.SIP_CALL_OPTION_CHANGED"; 121cf38b8464007ebf626fc0d61a646491fc3d794cdTyler Gunn 1223adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan /** 1233adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * Part of the ACTION_SIP_ADD_PHONE and ACTION_SIP_REMOVE_PHONE intents. 1243adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * Internal use only. 1253adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * @hide 1263adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan */ 1273adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan public static final String EXTRA_LOCAL_URI = "android:localSipUri"; 12898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 129e8782e2fdfd256296a0d1fd2a1c3f98d58103eaaHung-ying Tyan private static final String TAG = "SipManager"; 130e8782e2fdfd256296a0d1fd2a1c3f98d58103eaaHung-ying Tyan 13198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang private ISipService mSipService; 1323adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan private Context mContext; 13398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 13498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 1353adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * Creates a manager instance. Returns null if SIP API is not supported. 13698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 1373adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * @param context application context for creating the manager object 13869d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan * @return the manager instance or null if SIP API is not supported 13998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 1403adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan public static SipManager newInstance(Context context) { 1413adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan return (isApiSupported(context) ? new SipManager(context) : null); 14269d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan } 14369d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan 14469d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan /** 14569d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan * Returns true if the SIP API is supported by the system. 14669d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan */ 14769d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan public static boolean isApiSupported(Context context) { 14869d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan return context.getPackageManager().hasSystemFeature( 14969d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan PackageManager.FEATURE_SIP); 15069d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan } 15169d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan 15269d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan /** 15338ee75e8c0722118d26a23afe5b509b6a09302f4Hung-ying Tyan * Returns true if the system supports SIP-based VOIP API. 15469d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan */ 15569d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan public static boolean isVoipSupported(Context context) { 15669d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan return context.getPackageManager().hasSystemFeature( 15769d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan PackageManager.FEATURE_SIP_VOIP) && isApiSupported(context); 15898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 15998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 160d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan /** 161d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan * Returns true if SIP is only available on WIFI. 162d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan */ 163d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan public static boolean isSipWifiOnly(Context context) { 164d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan return context.getResources().getBoolean( 165d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan com.android.internal.R.bool.config_sip_wifi_only); 166d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan } 167d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan 1683adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan private SipManager(Context context) { 1693adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan mContext = context; 17069d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan createSipService(); 17198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 17298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 17369d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan private void createSipService() { 174f08fe9659343327dc29da410b64597b33613c732Brad Ebinger if (mSipService == null) { 175f08fe9659343327dc29da410b64597b33613c732Brad Ebinger IBinder b = ServiceManager.getService(Context.SIP_SERVICE); 176f08fe9659343327dc29da410b64597b33613c732Brad Ebinger mSipService = ISipService.Stub.asInterface(b); 177f08fe9659343327dc29da410b64597b33613c732Brad Ebinger } 178f08fe9659343327dc29da410b64597b33613c732Brad Ebinger } 179f08fe9659343327dc29da410b64597b33613c732Brad Ebinger 180f08fe9659343327dc29da410b64597b33613c732Brad Ebinger private void checkSipServiceConnection() throws SipException { 181f08fe9659343327dc29da410b64597b33613c732Brad Ebinger createSipService(); 182f08fe9659343327dc29da410b64597b33613c732Brad Ebinger if (mSipService == null) { 183f08fe9659343327dc29da410b64597b33613c732Brad Ebinger throw new SipException("SipService is dead and is restarting...", new Exception()); 184f08fe9659343327dc29da410b64597b33613c732Brad Ebinger } 18598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 18698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 18798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 18816b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * Opens the profile for making generic SIP calls. The caller may make subsequent calls 1893adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * through {@link #makeAudioCall}. If one also wants to receive calls on the 190845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * profile, use 191845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * {@link #open(SipProfile, PendingIntent, SipRegistrationListener)} 1923adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * instead. 19398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 19498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param localProfile the SIP profile to make calls from 19598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws SipException if the profile contains incorrect settings or 19698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * calling the SIP service results in an error 19798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 19898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public void open(SipProfile localProfile) throws SipException { 19998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang try { 200f08fe9659343327dc29da410b64597b33613c732Brad Ebinger checkSipServiceConnection(); 201d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav mSipService.open(localProfile, mContext.getOpPackageName()); 20298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } catch (RemoteException e) { 20398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new SipException("open()", e); 20498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 20598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 20698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 20798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 20816b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * Opens the profile for making calls and/or receiving generic SIP calls. The caller may 2093adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * make subsequent calls through {@link #makeAudioCall}. If the 2103adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * auto-registration option is enabled in the profile, the SIP service 2113adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * will register the profile to the corresponding SIP provider periodically 2124e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * in order to receive calls from the provider. When the SIP service 2134e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * receives a new call, it will send out an intent with the provided action 2144e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * string. The intent contains a call ID extra and an offer session 2154e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * description string extra. Use {@link #getCallId} and 2164e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * {@link #getOfferSessionDescription} to retrieve those extras. 21798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 21898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param localProfile the SIP profile to receive incoming calls for 219845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * @param incomingCallPendingIntent When an incoming call is received, the 220845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * SIP service will call 221845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * {@link PendingIntent#send(Context, int, Intent)} to send back the 222845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * intent to the caller with {@link #INCOMING_CALL_RESULT_CODE} as the 223845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * result code and the intent to fill in the call ID and session 224845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * description information. It cannot be null. 22598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param listener to listen to registration events; can be null 226845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * @see #getCallId 227845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * @see #getOfferSessionDescription 228845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * @see #takeAudioCall 229845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * @throws NullPointerException if {@code incomingCallPendingIntent} is null 23098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws SipException if the profile contains incorrect settings or 23198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * calling the SIP service results in an error 2324e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * @see #isIncomingCallIntent 2334e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * @see #getCallId 2344e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * @see #getOfferSessionDescription 23598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 23698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public void open(SipProfile localProfile, 237845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 23898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang SipRegistrationListener listener) throws SipException { 239845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan if (incomingCallPendingIntent == null) { 240845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan throw new NullPointerException( 241845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan "incomingCallPendingIntent cannot be null"); 242845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan } 24398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang try { 244f08fe9659343327dc29da410b64597b33613c732Brad Ebinger checkSipServiceConnection(); 245845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mSipService.open3(localProfile, incomingCallPendingIntent, 246d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav createRelay(listener, localProfile.getUriString()), 247d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav mContext.getOpPackageName()); 24898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } catch (RemoteException e) { 24998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new SipException("open()", e); 25098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 25198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 25298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 25398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 25498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Sets the listener to listen to registration events. No effect if the 255845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * profile has not been opened to receive calls (see 256845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * {@link #open(SipProfile, PendingIntent, SipRegistrationListener)}). 25798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 25898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param localProfileUri the URI of the profile 25998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param listener to listen to registration events; can be null 26098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws SipException if calling the SIP service results in an error 26198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 26298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public void setRegistrationListener(String localProfileUri, 26398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang SipRegistrationListener listener) throws SipException { 26498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang try { 265f08fe9659343327dc29da410b64597b33613c732Brad Ebinger checkSipServiceConnection(); 26698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang mSipService.setRegistrationListener( 267d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav localProfileUri, createRelay(listener, localProfileUri), 268d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav mContext.getOpPackageName()); 26998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } catch (RemoteException e) { 27098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new SipException("setRegistrationListener()", e); 27198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 27298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 27398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 27498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 27598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Closes the specified profile to not make/receive calls. All the resources 27698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * that were allocated to the profile are also released. 27798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 27898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param localProfileUri the URI of the profile to close 27998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws SipException if calling the SIP service results in an error 28098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 28198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public void close(String localProfileUri) throws SipException { 28298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang try { 283f08fe9659343327dc29da410b64597b33613c732Brad Ebinger checkSipServiceConnection(); 284d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav mSipService.close(localProfileUri, mContext.getOpPackageName()); 28598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } catch (RemoteException e) { 28698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new SipException("close()", e); 28798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 28898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 28998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 29098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 2913adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * Checks if the specified profile is opened in the SIP service for 2923adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * making and/or receiving calls. 29398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 29498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param localProfileUri the URI of the profile in question 29598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @return true if the profile is enabled to receive calls 29698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws SipException if calling the SIP service results in an error 29798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 29898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public boolean isOpened(String localProfileUri) throws SipException { 29998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang try { 300f08fe9659343327dc29da410b64597b33613c732Brad Ebinger checkSipServiceConnection(); 301d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return mSipService.isOpened(localProfileUri, mContext.getOpPackageName()); 30298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } catch (RemoteException e) { 30398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new SipException("isOpened()", e); 30498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 30598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 30698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 30798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 3083adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * Checks if the SIP service has successfully registered the profile to the 3093adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * SIP provider (specified in the profile) for receiving calls. Returning 3103adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * true from this method also implies the profile is opened 3113adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * ({@link #isOpened}). 31298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 31398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param localProfileUri the URI of the profile in question 3143adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * @return true if the profile is registered to the SIP provider; false if 3153adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * the profile has not been opened in the SIP service or the SIP 3163adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * service has not yet successfully registered the profile to the SIP 3173adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * provider 31898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws SipException if calling the SIP service results in an error 31998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 32098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public boolean isRegistered(String localProfileUri) throws SipException { 32198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang try { 322f08fe9659343327dc29da410b64597b33613c732Brad Ebinger checkSipServiceConnection(); 323d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return mSipService.isRegistered(localProfileUri, mContext.getOpPackageName()); 32498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } catch (RemoteException e) { 32598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new SipException("isRegistered()", e); 32698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 32798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 32898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 32998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 330f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan * Creates a {@link SipAudioCall} to make a call. The attempt will be timed 331f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan * out if the call is not established within {@code timeout} seconds and 33216b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * {@link SipAudioCall.Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)} 333f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan * will be called. 33498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 33598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param localProfile the SIP profile to make the call from 33698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param peerProfile the SIP profile to make the call to 33798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param listener to listen to the call events from {@link SipAudioCall}; 33898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * can be null 3394e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * @param timeout the timeout value in seconds. Default value (defined by 3404e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * SIP protocol) is used if {@code timeout} is zero or negative. 34198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @return a {@link SipAudioCall} object 34238ee75e8c0722118d26a23afe5b509b6a09302f4Hung-ying Tyan * @throws SipException if calling the SIP service results in an error or 34338ee75e8c0722118d26a23afe5b509b6a09302f4Hung-ying Tyan * VOIP API is not supported by the device 34416b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * @see SipAudioCall.Listener#onError 34538ee75e8c0722118d26a23afe5b509b6a09302f4Hung-ying Tyan * @see #isVoipSupported 34698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 3473adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan public SipAudioCall makeAudioCall(SipProfile localProfile, 348f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan SipProfile peerProfile, SipAudioCall.Listener listener, int timeout) 34998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throws SipException { 35038ee75e8c0722118d26a23afe5b509b6a09302f4Hung-ying Tyan if (!isVoipSupported(mContext)) { 35138ee75e8c0722118d26a23afe5b509b6a09302f4Hung-ying Tyan throw new SipException("VOIP API is not supported"); 35238ee75e8c0722118d26a23afe5b509b6a09302f4Hung-ying Tyan } 3533adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan SipAudioCall call = new SipAudioCall(mContext, localProfile); 35498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang call.setListener(listener); 3557a4ec7268fbfb56e22f1cb8497d37ed733d8aa8eHung-ying Tyan SipSession s = createSipSession(localProfile, null); 3567a4ec7268fbfb56e22f1cb8497d37ed733d8aa8eHung-ying Tyan call.makeCall(peerProfile, s, timeout); 35798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang return call; 35898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 35998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 36098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 361845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * Creates a {@link SipAudioCall} to make an audio call. The attempt will be 362845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * timed out if the call is not established within {@code timeout} seconds 363845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * and 36416b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * {@link SipAudioCall.Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)} 365f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan * will be called. 36698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 36798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param localProfileUri URI of the SIP profile to make the call from 36898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param peerProfileUri URI of the SIP profile to make the call to 36998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param listener to listen to the call events from {@link SipAudioCall}; 37098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * can be null 3714e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * @param timeout the timeout value in seconds. Default value (defined by 3724e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * SIP protocol) is used if {@code timeout} is zero or negative. 37398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @return a {@link SipAudioCall} object 37438ee75e8c0722118d26a23afe5b509b6a09302f4Hung-ying Tyan * @throws SipException if calling the SIP service results in an error or 37538ee75e8c0722118d26a23afe5b509b6a09302f4Hung-ying Tyan * VOIP API is not supported by the device 37616b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * @see SipAudioCall.Listener#onError 37738ee75e8c0722118d26a23afe5b509b6a09302f4Hung-ying Tyan * @see #isVoipSupported 37898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 3793adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan public SipAudioCall makeAudioCall(String localProfileUri, 380f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan String peerProfileUri, SipAudioCall.Listener listener, int timeout) 38198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throws SipException { 38238ee75e8c0722118d26a23afe5b509b6a09302f4Hung-ying Tyan if (!isVoipSupported(mContext)) { 38338ee75e8c0722118d26a23afe5b509b6a09302f4Hung-ying Tyan throw new SipException("VOIP API is not supported"); 38438ee75e8c0722118d26a23afe5b509b6a09302f4Hung-ying Tyan } 38598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang try { 3863adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan return makeAudioCall( 38798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang new SipProfile.Builder(localProfileUri).build(), 388f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan new SipProfile.Builder(peerProfileUri).build(), listener, 389f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan timeout); 39098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } catch (ParseException e) { 39198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new SipException("build SipProfile", e); 39298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 39398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 39498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 39598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 39698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Creates a {@link SipAudioCall} to take an incoming call. Before the call 39798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * is returned, the listener will receive a 398901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan * {@link SipAudioCall.Listener#onRinging} 39998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * callback. 40098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 40198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param incomingCallIntent the incoming call broadcast intent 40298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param listener to listen to the call events from {@link SipAudioCall}; 40398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * can be null 40498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @return a {@link SipAudioCall} object 40598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws SipException if calling the SIP service results in an error 40698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 4073adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan public SipAudioCall takeAudioCall(Intent incomingCallIntent, 4086577ac4cc93ee3670a5aceceb9a95260d41fe570Hung-ying Tyan SipAudioCall.Listener listener) throws SipException { 409b030e52a52acaf28ce68b1010aac007af909478dHung-ying Tyan if (incomingCallIntent == null) { 410b030e52a52acaf28ce68b1010aac007af909478dHung-ying Tyan throw new SipException("Cannot retrieve session with null intent"); 411b030e52a52acaf28ce68b1010aac007af909478dHung-ying Tyan } 41298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 41398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang String callId = getCallId(incomingCallIntent); 41498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang if (callId == null) { 41598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new SipException("Call ID missing in incoming call intent"); 41698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 41798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 4186d0ef774a2492b0996ded3a43c300c7f72a94897Chia-chi Yeh String offerSd = getOfferSessionDescription(incomingCallIntent); 41998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang if (offerSd == null) { 42098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new SipException("Session description missing in incoming " 42198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang + "call intent"); 42298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 42398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 42498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang try { 425f08fe9659343327dc29da410b64597b33613c732Brad Ebinger checkSipServiceConnection(); 426d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav ISipSession session = mSipService.getPendingSession(callId, 427d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav mContext.getOpPackageName()); 428b030e52a52acaf28ce68b1010aac007af909478dHung-ying Tyan if (session == null) { 429b030e52a52acaf28ce68b1010aac007af909478dHung-ying Tyan throw new SipException("No pending session for the call"); 430b030e52a52acaf28ce68b1010aac007af909478dHung-ying Tyan } 4313adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan SipAudioCall call = new SipAudioCall( 4323adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan mContext, session.getLocalProfile()); 4333adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan call.attachCall(new SipSession(session), offerSd); 43498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang call.setListener(listener); 43598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang return call; 43698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } catch (Throwable t) { 43798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new SipException("takeAudioCall()", t); 43898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 43998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 44098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 44198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 44298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Checks if the intent is an incoming call broadcast intent. 44398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 44498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param intent the intent in question 44598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @return true if the intent is an incoming call broadcast intent 44698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 44798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public static boolean isIncomingCallIntent(Intent intent) { 44898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang if (intent == null) return false; 44998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang String callId = getCallId(intent); 4506d0ef774a2492b0996ded3a43c300c7f72a94897Chia-chi Yeh String offerSd = getOfferSessionDescription(intent); 45198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang return ((callId != null) && (offerSd != null)); 45298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 45398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 45498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 45598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Gets the call ID from the specified incoming call broadcast intent. 45698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 45798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param incomingCallIntent the incoming call broadcast intent 45898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @return the call ID or null if the intent does not contain it 45998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 46098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public static String getCallId(Intent incomingCallIntent) { 4613adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan return incomingCallIntent.getStringExtra(EXTRA_CALL_ID); 46298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 46398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 46498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 46598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Gets the offer session description from the specified incoming call 46698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * broadcast intent. 46798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 46898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param incomingCallIntent the incoming call broadcast intent 46998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @return the offer session description or null if the intent does not 47098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * have it 47198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 4726d0ef774a2492b0996ded3a43c300c7f72a94897Chia-chi Yeh public static String getOfferSessionDescription(Intent incomingCallIntent) { 4733adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan return incomingCallIntent.getStringExtra(EXTRA_OFFER_SD); 47498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 47598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 47698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 47798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Creates an incoming call broadcast intent. 47898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 47998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param callId the call ID of the incoming call 48098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param sessionDescription the session description of the incoming call 48198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @return the incoming call intent 48298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @hide 48398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 4843adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan public static Intent createIncomingCallBroadcast(String callId, 4853adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan String sessionDescription) { 4863adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan Intent intent = new Intent(); 4873adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan intent.putExtra(EXTRA_CALL_ID, callId); 4883adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan intent.putExtra(EXTRA_OFFER_SD, sessionDescription); 48998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang return intent; 49098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 49198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 49298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 4933adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * Manually registers the profile to the corresponding SIP provider for 494845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * receiving calls. 495845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * {@link #open(SipProfile, PendingIntent, SipRegistrationListener)} is 496845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * still needed to be called at least once in order for the SIP service to 49716b441b4ad92c6a5cbc6f27cb3705eaaaaee20c1Scott Main * notify the caller with the {@link android.app.PendingIntent} when an incoming call is 498845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan * received. 49998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 50098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param localProfile the SIP profile to register with 501901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan * @param expiryTime registration expiration time (in seconds) 50298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param listener to listen to the registration events 50398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws SipException if calling the SIP service results in an error 50498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 50598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public void register(SipProfile localProfile, int expiryTime, 50698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang SipRegistrationListener listener) throws SipException { 50798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang try { 508f08fe9659343327dc29da410b64597b33613c732Brad Ebinger checkSipServiceConnection(); 509f3d1e1fd0f86eb956c82634c075b167dc367757cHung-ying Tyan ISipSession session = mSipService.createSession(localProfile, 510d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav createRelay(listener, localProfile.getUriString()), 511d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav mContext.getOpPackageName()); 512088ef46d8b5a849d80a257670bb2a809713b7bf0Masahiko Endo if (session == null) { 513088ef46d8b5a849d80a257670bb2a809713b7bf0Masahiko Endo throw new SipException( 514088ef46d8b5a849d80a257670bb2a809713b7bf0Masahiko Endo "SipService.createSession() returns null"); 515088ef46d8b5a849d80a257670bb2a809713b7bf0Masahiko Endo } 51698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang session.register(expiryTime); 51798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } catch (RemoteException e) { 51898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new SipException("register()", e); 51998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 52098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 52198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 52298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 5233adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * Manually unregisters the profile from the corresponding SIP provider for 5243adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * stop receiving further calls. This may interference with the auto 5253adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * registration process in the SIP service if the auto-registration option 5263adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * in the profile is enabled. 52798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 52898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param localProfile the SIP profile to register with 52998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param listener to listen to the registration events 53098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws SipException if calling the SIP service results in an error 53198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 53298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public void unregister(SipProfile localProfile, 53398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang SipRegistrationListener listener) throws SipException { 53498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang try { 535f08fe9659343327dc29da410b64597b33613c732Brad Ebinger checkSipServiceConnection(); 536f3d1e1fd0f86eb956c82634c075b167dc367757cHung-ying Tyan ISipSession session = mSipService.createSession(localProfile, 537d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav createRelay(listener, localProfile.getUriString()), 538d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav mContext.getOpPackageName()); 539088ef46d8b5a849d80a257670bb2a809713b7bf0Masahiko Endo if (session == null) { 540088ef46d8b5a849d80a257670bb2a809713b7bf0Masahiko Endo throw new SipException( 541088ef46d8b5a849d80a257670bb2a809713b7bf0Masahiko Endo "SipService.createSession() returns null"); 542088ef46d8b5a849d80a257670bb2a809713b7bf0Masahiko Endo } 54398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang session.unregister(); 54498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } catch (RemoteException e) { 54598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new SipException("unregister()", e); 54698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 54798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 54898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 54998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 5504e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * Gets the {@link SipSession} that handles the incoming call. For audio 55198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * calls, consider to use {@link SipAudioCall} to handle the incoming call. 552901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan * See {@link #takeAudioCall}. Note that the method may be called only once 553901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan * for the same intent. For subsequent calls on the same intent, the method 554901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan * returns null. 55598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 55698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param incomingCallIntent the incoming call broadcast intent 55798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @return the session object that handles the incoming call 55898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 5594e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan public SipSession getSessionFor(Intent incomingCallIntent) 56098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throws SipException { 56198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang try { 562f08fe9659343327dc29da410b64597b33613c732Brad Ebinger checkSipServiceConnection(); 56398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang String callId = getCallId(incomingCallIntent); 564d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav ISipSession s = mSipService.getPendingSession(callId, 565d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav mContext.getOpPackageName()); 566088ef46d8b5a849d80a257670bb2a809713b7bf0Masahiko Endo return ((s == null) ? null : new SipSession(s)); 56798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } catch (RemoteException e) { 56898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new SipException("getSessionFor()", e); 56998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 57098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 57198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 57298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang private static ISipSessionListener createRelay( 573f3d1e1fd0f86eb956c82634c075b167dc367757cHung-ying Tyan SipRegistrationListener listener, String uri) { 574f3d1e1fd0f86eb956c82634c075b167dc367757cHung-ying Tyan return ((listener == null) ? null : new ListenerRelay(listener, uri)); 57598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 57698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 57798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 5784e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * Creates a {@link SipSession} with the specified profile. Use other 5794e22f5d6687c18440e2f38c7e242d66ad834d1d7Hung-ying Tyan * methods, if applicable, instead of interacting with {@link SipSession} 58098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * directly. 58198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 58298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param localProfile the SIP profile the session is associated with 58398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param listener to listen to SIP session events 58498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 5853adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan public SipSession createSipSession(SipProfile localProfile, 5863adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan SipSession.Listener listener) throws SipException { 58798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang try { 588f08fe9659343327dc29da410b64597b33613c732Brad Ebinger checkSipServiceConnection(); 589d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav ISipSession s = mSipService.createSession(localProfile, null, 590d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav mContext.getOpPackageName()); 591b030e52a52acaf28ce68b1010aac007af909478dHung-ying Tyan if (s == null) { 592b030e52a52acaf28ce68b1010aac007af909478dHung-ying Tyan throw new SipException( 593b030e52a52acaf28ce68b1010aac007af909478dHung-ying Tyan "Failed to create SipSession; network unavailable?"); 594b030e52a52acaf28ce68b1010aac007af909478dHung-ying Tyan } 5953adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan return new SipSession(s, listener); 59698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } catch (RemoteException e) { 59798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new SipException("createSipSession()", e); 59898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 59998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 60098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 60198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 60298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Gets the list of profiles hosted by the SIP service. The user information 60398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * (username, password and display name) are crossed out. 60498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @hide 60598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 606f08fe9659343327dc29da410b64597b33613c732Brad Ebinger public SipProfile[] getListOfProfiles() throws SipException { 60798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang try { 608f08fe9659343327dc29da410b64597b33613c732Brad Ebinger checkSipServiceConnection(); 609d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return mSipService.getListOfProfiles(mContext.getOpPackageName()); 61098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } catch (RemoteException e) { 611b030e52a52acaf28ce68b1010aac007af909478dHung-ying Tyan return new SipProfile[0]; 61298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 61398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 61498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 61598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang private static class ListenerRelay extends SipSessionAdapter { 61698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang private SipRegistrationListener mListener; 617f3d1e1fd0f86eb956c82634c075b167dc367757cHung-ying Tyan private String mUri; 61898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 61998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang // listener must not be null 620f3d1e1fd0f86eb956c82634c075b167dc367757cHung-ying Tyan public ListenerRelay(SipRegistrationListener listener, String uri) { 62198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang mListener = listener; 622f3d1e1fd0f86eb956c82634c075b167dc367757cHung-ying Tyan mUri = uri; 62398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 62498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 62598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang private String getUri(ISipSession session) { 62698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang try { 627d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan return ((session == null) 628f3d1e1fd0f86eb956c82634c075b167dc367757cHung-ying Tyan ? mUri 629d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan : session.getLocalProfile().getUriString()); 630e8782e2fdfd256296a0d1fd2a1c3f98d58103eaaHung-ying Tyan } catch (Throwable e) { 631e8782e2fdfd256296a0d1fd2a1c3f98d58103eaaHung-ying Tyan // SipService died? SIP stack died? 6329329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.e(TAG, "getUri(): ", e); 633e8782e2fdfd256296a0d1fd2a1c3f98d58103eaaHung-ying Tyan return null; 63498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 63598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 63698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 63798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang @Override 63898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public void onRegistering(ISipSession session) { 63998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang mListener.onRegistering(getUri(session)); 64098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 64198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 64298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang @Override 64398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public void onRegistrationDone(ISipSession session, int duration) { 64498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang long expiryTime = duration; 64598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang if (duration > 0) expiryTime += System.currentTimeMillis(); 64698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang mListener.onRegistrationDone(getUri(session), expiryTime); 64798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 64898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 64998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang @Override 650a0171082cfc4b860a82dcf5ebbd498b253f1032fHung-ying Tyan public void onRegistrationFailed(ISipSession session, int errorCode, 65198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang String message) { 652a0171082cfc4b860a82dcf5ebbd498b253f1032fHung-ying Tyan mListener.onRegistrationFailed(getUri(session), errorCode, message); 65398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 65498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 65598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang @Override 65698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public void onRegistrationTimeout(ISipSession session) { 65798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang mListener.onRegistrationFailed(getUri(session), 6581ab079168ccc185408a8691c6b804021d79f7376Hung-ying Tyan SipErrorCode.TIME_OUT, "registration timed out"); 65998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 66098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 66198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang} 662