1363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang/* 2363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Copyright (C) 2010 The Android Open Source Project 3363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 4363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Licensed under the Apache License, Version 2.0 (the "License"); 5363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * you may not use this file except in compliance with the License. 6363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * You may obtain a copy of the License at 7363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 8363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * http://www.apache.org/licenses/LICENSE-2.0 9363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 10363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Unless required by applicable law or agreed to in writing, software 11363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * distributed under the License is distributed on an "AS IS" BASIS, 12363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * See the License for the specific language governing permissions and 14363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * limitations under the License. 15363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 16363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 17363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangpackage android.net.sip; 18363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 19323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyanimport android.app.PendingIntent; 20363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport android.content.Context; 21363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport android.content.Intent; 223424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyanimport android.content.pm.PackageManager; 23363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport android.os.IBinder; 24363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport android.os.Looper; 25363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport android.os.RemoteException; 26363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport android.os.ServiceManager; 279ea96c6cade1f25d4d77dcbd24854df431548b36Hung-ying Tyanimport android.util.Log; 28363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 29363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport java.text.ParseException; 30363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 31363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang/** 3202b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * Provides APIs for SIP tasks, such as initiating SIP connections, and provides access to related 3302b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * SIP services. This class is the starting point for any SIP actions. You can acquire an instance 3402b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * of it with {@link #newInstance newInstance()}.</p> 3502b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * <p>The APIs in this class allows you to:</p> 36363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * <ul> 3702b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * <li>Create a {@link SipSession} to get ready for making calls or listen for incoming calls. See 3802b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * {@link #createSipSession createSipSession()} and {@link #getSessionFor getSessionFor()}.</li> 3902b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * <li>Initiate and receive generic SIP calls or audio-only SIP calls. Generic SIP calls may 4002b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * be video, audio, or other, and are initiated with {@link #open open()}. Audio-only SIP calls 4102b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * should be handled with a {@link SipAudioCall}, which you can acquire with {@link 4202b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * #makeAudioCall makeAudioCall()} and {@link #takeAudioCall takeAudioCall()}.</li> 4302b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * <li>Register and unregister with a SIP service provider, with 4402b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * {@link #register register()} and {@link #unregister unregister()}.</li> 4502b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * <li>Verify session connectivity, with {@link #isOpened isOpened()} and 4602b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * {@link #isRegistered isRegistered()}.</li> 47363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * </ul> 4802b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * <p class="note"><strong>Note:</strong> Not all Android-powered devices support VOIP calls using 4902b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * SIP. You should always call {@link android.net.sip.SipManager#isVoipSupported 5002b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * isVoipSupported()} to verify that the device supports VOIP calling and {@link 5102b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * android.net.sip.SipManager#isApiSupported isApiSupported()} to verify that the device supports 523aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * the SIP APIs. Your application must also request the {@link 5302b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * android.Manifest.permission#INTERNET} and {@link android.Manifest.permission#USE_SIP} 5402b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * permissions.</p> 553aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * 563aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <div class="special reference"> 573aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <h3>Developer Guides</h3> 583aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <p>For more information about using SIP, read the 593aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <a href="{@docRoot}guide/topics/network/sip.html">Session Initiation Protocol</a> 603aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * developer guide.</p> 613aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * </div> 62363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 63363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangpublic class SipManager { 6484a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan /** 65323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * The result code to be sent back with the incoming call 66323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * {@link PendingIntent}. 67323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * @see #open(SipProfile, PendingIntent, SipRegistrationListener) 68323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan */ 69323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan public static final int INCOMING_CALL_RESULT_CODE = 101; 70323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan 7108faac3c26e12863858e1534985dd950193f755fHung-ying Tyan /** 7208faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * Key to retrieve the call ID from an incoming call intent. 7308faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * @see #open(SipProfile, PendingIntent, SipRegistrationListener) 7408faac3c26e12863858e1534985dd950193f755fHung-ying Tyan */ 75323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan public static final String EXTRA_CALL_ID = "android:sipCallID"; 76323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan 7708faac3c26e12863858e1534985dd950193f755fHung-ying Tyan /** 7808faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * Key to retrieve the offered session description from an incoming call 7908faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * intent. 8008faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * @see #open(SipProfile, PendingIntent, SipRegistrationListener) 8108faac3c26e12863858e1534985dd950193f755fHung-ying Tyan */ 82323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan public static final String EXTRA_OFFER_SD = "android:sipOfferSD"; 83323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan 84323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan /** 859db99a4dc10ac0d5d3751f03ea51c0fed217d2f8Hung-ying Tyan * Action to broadcast when SipService is up. 869db99a4dc10ac0d5d3751f03ea51c0fed217d2f8Hung-ying Tyan * Internal use only. 879db99a4dc10ac0d5d3751f03ea51c0fed217d2f8Hung-ying Tyan * @hide 889db99a4dc10ac0d5d3751f03ea51c0fed217d2f8Hung-ying Tyan */ 899db99a4dc10ac0d5d3751f03ea51c0fed217d2f8Hung-ying Tyan public static final String ACTION_SIP_SERVICE_UP = 909db99a4dc10ac0d5d3751f03ea51c0fed217d2f8Hung-ying Tyan "android.net.sip.SIP_SERVICE_UP"; 919db99a4dc10ac0d5d3751f03ea51c0fed217d2f8Hung-ying Tyan /** 9284a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * Action string for the incoming call intent for the Phone app. 9384a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * Internal use only. 9484a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * @hide 9584a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan */ 9684a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan public static final String ACTION_SIP_INCOMING_CALL = 97363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang "com.android.phone.SIP_INCOMING_CALL"; 9884a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan /** 9984a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * Action string for the add-phone intent. 10084a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * Internal use only. 10184a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * @hide 10284a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan */ 10384a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan public static final String ACTION_SIP_ADD_PHONE = 104363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang "com.android.phone.SIP_ADD_PHONE"; 10584a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan /** 10684a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * Action string for the remove-phone intent. 10784a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * Internal use only. 10884a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * @hide 10984a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan */ 11084a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan public static final String ACTION_SIP_REMOVE_PHONE = 111363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang "com.android.phone.SIP_REMOVE_PHONE"; 11284a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan /** 11384a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * Part of the ACTION_SIP_ADD_PHONE and ACTION_SIP_REMOVE_PHONE intents. 11484a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * Internal use only. 11584a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * @hide 11684a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan */ 11784a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan public static final String EXTRA_LOCAL_URI = "android:localSipUri"; 118363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 1199ea96c6cade1f25d4d77dcbd24854df431548b36Hung-ying Tyan private static final String TAG = "SipManager"; 1209ea96c6cade1f25d4d77dcbd24854df431548b36Hung-ying Tyan 121363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private ISipService mSipService; 12284a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan private Context mContext; 123363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 124363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 12584a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * Creates a manager instance. Returns null if SIP API is not supported. 126363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 12784a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * @param context application context for creating the manager object 1283424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan * @return the manager instance or null if SIP API is not supported 129363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 13084a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan public static SipManager newInstance(Context context) { 13184a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan return (isApiSupported(context) ? new SipManager(context) : null); 1323424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan } 1333424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan 1343424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan /** 1353424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan * Returns true if the SIP API is supported by the system. 1363424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan */ 1373424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan public static boolean isApiSupported(Context context) { 1383424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan return context.getPackageManager().hasSystemFeature( 1393424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan PackageManager.FEATURE_SIP); 1403424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan } 1413424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan 1423424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan /** 1435bd3782f244212cd8ef51bf9f3578869b08b4e18Hung-ying Tyan * Returns true if the system supports SIP-based VOIP API. 1443424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan */ 1453424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan public static boolean isVoipSupported(Context context) { 1463424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan return context.getPackageManager().hasSystemFeature( 1473424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan PackageManager.FEATURE_SIP_VOIP) && isApiSupported(context); 148363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 149363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 150c4b87477c076d61062950becc132b7483e3fb198Hung-ying Tyan /** 151c4b87477c076d61062950becc132b7483e3fb198Hung-ying Tyan * Returns true if SIP is only available on WIFI. 152c4b87477c076d61062950becc132b7483e3fb198Hung-ying Tyan */ 153c4b87477c076d61062950becc132b7483e3fb198Hung-ying Tyan public static boolean isSipWifiOnly(Context context) { 154c4b87477c076d61062950becc132b7483e3fb198Hung-ying Tyan return context.getResources().getBoolean( 155c4b87477c076d61062950becc132b7483e3fb198Hung-ying Tyan com.android.internal.R.bool.config_sip_wifi_only); 156c4b87477c076d61062950becc132b7483e3fb198Hung-ying Tyan } 157c4b87477c076d61062950becc132b7483e3fb198Hung-ying Tyan 15884a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan private SipManager(Context context) { 15984a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan mContext = context; 1603424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan createSipService(); 161363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 162363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 1633424c02e6b931a8bbd651ae75217bebd008b2605Hung-ying Tyan private void createSipService() { 164cde66df44240cfe5a7bec12ac52464c3bf26c14fChung-yih Wang IBinder b = ServiceManager.getService(Context.SIP_SERVICE); 165363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mSipService = ISipService.Stub.asInterface(b); 166363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 167363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 168363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 16902b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * Opens the profile for making generic SIP calls. The caller may make subsequent calls 17084a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * through {@link #makeAudioCall}. If one also wants to receive calls on the 171323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * profile, use 172323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * {@link #open(SipProfile, PendingIntent, SipRegistrationListener)} 17384a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * instead. 174363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 175363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param localProfile the SIP profile to make calls from 176363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws SipException if the profile contains incorrect settings or 177363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * calling the SIP service results in an error 178363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 179363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void open(SipProfile localProfile) throws SipException { 180363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang try { 181363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mSipService.open(localProfile); 182363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } catch (RemoteException e) { 183363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new SipException("open()", e); 184363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 185363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 186363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 187363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 18802b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * Opens the profile for making calls and/or receiving generic SIP calls. The caller may 18984a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * make subsequent calls through {@link #makeAudioCall}. If the 19084a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * auto-registration option is enabled in the profile, the SIP service 19184a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * will register the profile to the corresponding SIP provider periodically 19208faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * in order to receive calls from the provider. When the SIP service 19308faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * receives a new call, it will send out an intent with the provided action 19408faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * string. The intent contains a call ID extra and an offer session 19508faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * description string extra. Use {@link #getCallId} and 19608faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * {@link #getOfferSessionDescription} to retrieve those extras. 197363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 198363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param localProfile the SIP profile to receive incoming calls for 199323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * @param incomingCallPendingIntent When an incoming call is received, the 200323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * SIP service will call 201323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * {@link PendingIntent#send(Context, int, Intent)} to send back the 202323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * intent to the caller with {@link #INCOMING_CALL_RESULT_CODE} as the 203323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * result code and the intent to fill in the call ID and session 204323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * description information. It cannot be null. 205363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param listener to listen to registration events; can be null 206323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * @see #getCallId 207323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * @see #getOfferSessionDescription 208323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * @see #takeAudioCall 209323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * @throws NullPointerException if {@code incomingCallPendingIntent} is null 210363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws SipException if the profile contains incorrect settings or 211363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * calling the SIP service results in an error 21208faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * @see #isIncomingCallIntent 21308faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * @see #getCallId 21408faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * @see #getOfferSessionDescription 215363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 216363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void open(SipProfile localProfile, 217323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan PendingIntent incomingCallPendingIntent, 218363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang SipRegistrationListener listener) throws SipException { 219323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan if (incomingCallPendingIntent == null) { 220323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan throw new NullPointerException( 221323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan "incomingCallPendingIntent cannot be null"); 222323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan } 223363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang try { 224323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan mSipService.open3(localProfile, incomingCallPendingIntent, 2259e1d308e993d451882456e44cfaacae63df7a496Hung-ying Tyan createRelay(listener, localProfile.getUriString())); 226363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } catch (RemoteException e) { 227363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new SipException("open()", e); 228363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 229363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 230363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 231363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 232363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Sets the listener to listen to registration events. No effect if the 233323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * profile has not been opened to receive calls (see 234323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * {@link #open(SipProfile, PendingIntent, SipRegistrationListener)}). 235363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 236363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param localProfileUri the URI of the profile 237363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param listener to listen to registration events; can be null 238363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws SipException if calling the SIP service results in an error 239363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 240363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void setRegistrationListener(String localProfileUri, 241363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang SipRegistrationListener listener) throws SipException { 242363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang try { 243363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mSipService.setRegistrationListener( 2449e1d308e993d451882456e44cfaacae63df7a496Hung-ying Tyan localProfileUri, createRelay(listener, localProfileUri)); 245363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } catch (RemoteException e) { 246363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new SipException("setRegistrationListener()", e); 247363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 248363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 249363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 250363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 251363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Closes the specified profile to not make/receive calls. All the resources 252363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * that were allocated to the profile are also released. 253363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 254363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param localProfileUri the URI of the profile to close 255363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws SipException if calling the SIP service results in an error 256363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 257363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void close(String localProfileUri) throws SipException { 258363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang try { 259363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mSipService.close(localProfileUri); 260363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } catch (RemoteException e) { 261363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new SipException("close()", e); 262363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 263363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 264363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 265363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 26684a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * Checks if the specified profile is opened in the SIP service for 26784a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * making and/or receiving calls. 268363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 269363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param localProfileUri the URI of the profile in question 270363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @return true if the profile is enabled to receive calls 271363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws SipException if calling the SIP service results in an error 272363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 273363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public boolean isOpened(String localProfileUri) throws SipException { 274363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang try { 275363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return mSipService.isOpened(localProfileUri); 276363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } catch (RemoteException e) { 277363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new SipException("isOpened()", e); 278363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 279363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 280363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 281363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 28284a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * Checks if the SIP service has successfully registered the profile to the 28384a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * SIP provider (specified in the profile) for receiving calls. Returning 28484a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * true from this method also implies the profile is opened 28584a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * ({@link #isOpened}). 286363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 287363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param localProfileUri the URI of the profile in question 28884a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * @return true if the profile is registered to the SIP provider; false if 28984a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * the profile has not been opened in the SIP service or the SIP 29084a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * service has not yet successfully registered the profile to the SIP 29184a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * provider 292363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws SipException if calling the SIP service results in an error 293363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 294363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public boolean isRegistered(String localProfileUri) throws SipException { 295363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang try { 296363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return mSipService.isRegistered(localProfileUri); 297363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } catch (RemoteException e) { 298363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new SipException("isRegistered()", e); 299363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 300363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 301363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 302363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 3039352cf1a4d46492fc48a20f7d825a9bcb6e8b365Hung-ying Tyan * Creates a {@link SipAudioCall} to make a call. The attempt will be timed 3049352cf1a4d46492fc48a20f7d825a9bcb6e8b365Hung-ying Tyan * out if the call is not established within {@code timeout} seconds and 30502b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * {@link SipAudioCall.Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)} 3069352cf1a4d46492fc48a20f7d825a9bcb6e8b365Hung-ying Tyan * will be called. 307363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 308363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param localProfile the SIP profile to make the call from 309363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param peerProfile the SIP profile to make the call to 310363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param listener to listen to the call events from {@link SipAudioCall}; 311363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * can be null 31208faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * @param timeout the timeout value in seconds. Default value (defined by 31308faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * SIP protocol) is used if {@code timeout} is zero or negative. 314363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @return a {@link SipAudioCall} object 3155bd3782f244212cd8ef51bf9f3578869b08b4e18Hung-ying Tyan * @throws SipException if calling the SIP service results in an error or 3165bd3782f244212cd8ef51bf9f3578869b08b4e18Hung-ying Tyan * VOIP API is not supported by the device 31702b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * @see SipAudioCall.Listener#onError 3185bd3782f244212cd8ef51bf9f3578869b08b4e18Hung-ying Tyan * @see #isVoipSupported 319363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 32084a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan public SipAudioCall makeAudioCall(SipProfile localProfile, 3219352cf1a4d46492fc48a20f7d825a9bcb6e8b365Hung-ying Tyan SipProfile peerProfile, SipAudioCall.Listener listener, int timeout) 322363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throws SipException { 3235bd3782f244212cd8ef51bf9f3578869b08b4e18Hung-ying Tyan if (!isVoipSupported(mContext)) { 3245bd3782f244212cd8ef51bf9f3578869b08b4e18Hung-ying Tyan throw new SipException("VOIP API is not supported"); 3255bd3782f244212cd8ef51bf9f3578869b08b4e18Hung-ying Tyan } 32684a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan SipAudioCall call = new SipAudioCall(mContext, localProfile); 327363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang call.setListener(listener); 3283a4197e642e9c70f1fe00c2cba30f0f957d36bfcHung-ying Tyan SipSession s = createSipSession(localProfile, null); 3293a4197e642e9c70f1fe00c2cba30f0f957d36bfcHung-ying Tyan call.makeCall(peerProfile, s, timeout); 330363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return call; 331363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 332363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 333363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 334323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * Creates a {@link SipAudioCall} to make an audio call. The attempt will be 335323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * timed out if the call is not established within {@code timeout} seconds 336323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * and 33702b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * {@link SipAudioCall.Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)} 3389352cf1a4d46492fc48a20f7d825a9bcb6e8b365Hung-ying Tyan * will be called. 339363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 340363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param localProfileUri URI of the SIP profile to make the call from 341363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param peerProfileUri URI of the SIP profile to make the call to 342363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param listener to listen to the call events from {@link SipAudioCall}; 343363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * can be null 34408faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * @param timeout the timeout value in seconds. Default value (defined by 34508faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * SIP protocol) is used if {@code timeout} is zero or negative. 346363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @return a {@link SipAudioCall} object 3475bd3782f244212cd8ef51bf9f3578869b08b4e18Hung-ying Tyan * @throws SipException if calling the SIP service results in an error or 3485bd3782f244212cd8ef51bf9f3578869b08b4e18Hung-ying Tyan * VOIP API is not supported by the device 34902b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * @see SipAudioCall.Listener#onError 3505bd3782f244212cd8ef51bf9f3578869b08b4e18Hung-ying Tyan * @see #isVoipSupported 351363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 35284a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan public SipAudioCall makeAudioCall(String localProfileUri, 3539352cf1a4d46492fc48a20f7d825a9bcb6e8b365Hung-ying Tyan String peerProfileUri, SipAudioCall.Listener listener, int timeout) 354363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throws SipException { 3555bd3782f244212cd8ef51bf9f3578869b08b4e18Hung-ying Tyan if (!isVoipSupported(mContext)) { 3565bd3782f244212cd8ef51bf9f3578869b08b4e18Hung-ying Tyan throw new SipException("VOIP API is not supported"); 3575bd3782f244212cd8ef51bf9f3578869b08b4e18Hung-ying Tyan } 358363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang try { 35984a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan return makeAudioCall( 360363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang new SipProfile.Builder(localProfileUri).build(), 3619352cf1a4d46492fc48a20f7d825a9bcb6e8b365Hung-ying Tyan new SipProfile.Builder(peerProfileUri).build(), listener, 3629352cf1a4d46492fc48a20f7d825a9bcb6e8b365Hung-ying Tyan timeout); 363363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } catch (ParseException e) { 364363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new SipException("build SipProfile", e); 365363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 366363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 367363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 368363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 369363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Creates a {@link SipAudioCall} to take an incoming call. Before the call 370363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * is returned, the listener will receive a 371286bb5a00bdb9f0cb0815aef441ec72f231c84eaHung-ying Tyan * {@link SipAudioCall.Listener#onRinging} 372363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * callback. 373363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 374363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param incomingCallIntent the incoming call broadcast intent 375363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param listener to listen to the call events from {@link SipAudioCall}; 376363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * can be null 377363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @return a {@link SipAudioCall} object 378363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws SipException if calling the SIP service results in an error 379363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 38084a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan public SipAudioCall takeAudioCall(Intent incomingCallIntent, 3819b449e5606786f7c197679f8f9d25985308bfb72Hung-ying Tyan SipAudioCall.Listener listener) throws SipException { 3828d1b2a17d9935819ec96f1b5fca0e9945f564eaaHung-ying Tyan if (incomingCallIntent == null) { 3838d1b2a17d9935819ec96f1b5fca0e9945f564eaaHung-ying Tyan throw new SipException("Cannot retrieve session with null intent"); 3848d1b2a17d9935819ec96f1b5fca0e9945f564eaaHung-ying Tyan } 385363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 386363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang String callId = getCallId(incomingCallIntent); 387363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (callId == null) { 388363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new SipException("Call ID missing in incoming call intent"); 389363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 390363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 39195b15c35608fe3ea679c8a478c6cbd841623371eChia-chi Yeh String offerSd = getOfferSessionDescription(incomingCallIntent); 392363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (offerSd == null) { 393363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new SipException("Session description missing in incoming " 394363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang + "call intent"); 395363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 396363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 397363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang try { 398363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang ISipSession session = mSipService.getPendingSession(callId); 3998d1b2a17d9935819ec96f1b5fca0e9945f564eaaHung-ying Tyan if (session == null) { 4008d1b2a17d9935819ec96f1b5fca0e9945f564eaaHung-ying Tyan throw new SipException("No pending session for the call"); 4018d1b2a17d9935819ec96f1b5fca0e9945f564eaaHung-ying Tyan } 40284a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan SipAudioCall call = new SipAudioCall( 40384a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan mContext, session.getLocalProfile()); 40484a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan call.attachCall(new SipSession(session), offerSd); 405363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang call.setListener(listener); 406363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return call; 407363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } catch (Throwable t) { 408363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new SipException("takeAudioCall()", t); 409363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 410363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 411363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 412363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 413363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Checks if the intent is an incoming call broadcast intent. 414363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 415363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param intent the intent in question 416363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @return true if the intent is an incoming call broadcast intent 417363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 418363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public static boolean isIncomingCallIntent(Intent intent) { 419363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (intent == null) return false; 420363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang String callId = getCallId(intent); 42195b15c35608fe3ea679c8a478c6cbd841623371eChia-chi Yeh String offerSd = getOfferSessionDescription(intent); 422363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return ((callId != null) && (offerSd != null)); 423363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 424363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 425363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 426363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Gets the call ID from the specified incoming call broadcast intent. 427363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 428363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param incomingCallIntent the incoming call broadcast intent 429363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @return the call ID or null if the intent does not contain it 430363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 431363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public static String getCallId(Intent incomingCallIntent) { 43284a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan return incomingCallIntent.getStringExtra(EXTRA_CALL_ID); 433363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 434363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 435363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 436363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Gets the offer session description from the specified incoming call 437363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * broadcast intent. 438363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 439363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param incomingCallIntent the incoming call broadcast intent 440363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @return the offer session description or null if the intent does not 441363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * have it 442363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 44395b15c35608fe3ea679c8a478c6cbd841623371eChia-chi Yeh public static String getOfferSessionDescription(Intent incomingCallIntent) { 44484a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan return incomingCallIntent.getStringExtra(EXTRA_OFFER_SD); 445363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 446363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 447363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 448363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Creates an incoming call broadcast intent. 449363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 450363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param callId the call ID of the incoming call 451363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param sessionDescription the session description of the incoming call 452363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @return the incoming call intent 453363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @hide 454363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 45584a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan public static Intent createIncomingCallBroadcast(String callId, 45684a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan String sessionDescription) { 45784a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan Intent intent = new Intent(); 45884a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan intent.putExtra(EXTRA_CALL_ID, callId); 45984a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan intent.putExtra(EXTRA_OFFER_SD, sessionDescription); 460363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return intent; 461363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 462363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 463363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 46484a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * Manually registers the profile to the corresponding SIP provider for 465323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * receiving calls. 466323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * {@link #open(SipProfile, PendingIntent, SipRegistrationListener)} is 467323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * still needed to be called at least once in order for the SIP service to 46802b1d685cc287d7c53141872b3d80be4ee5dd59eScott Main * notify the caller with the {@link android.app.PendingIntent} when an incoming call is 469323d3671ac813df8dd173f3f4d6cb681ee29f740Hung-ying Tyan * received. 470363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 471363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param localProfile the SIP profile to register with 472286bb5a00bdb9f0cb0815aef441ec72f231c84eaHung-ying Tyan * @param expiryTime registration expiration time (in seconds) 473363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param listener to listen to the registration events 474363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws SipException if calling the SIP service results in an error 475363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 476363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void register(SipProfile localProfile, int expiryTime, 477363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang SipRegistrationListener listener) throws SipException { 478363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang try { 4799e1d308e993d451882456e44cfaacae63df7a496Hung-ying Tyan ISipSession session = mSipService.createSession(localProfile, 4809e1d308e993d451882456e44cfaacae63df7a496Hung-ying Tyan createRelay(listener, localProfile.getUriString())); 48125ccbb97ffd3298caede635f29445073e845cfc3Masahiko Endo if (session == null) { 48225ccbb97ffd3298caede635f29445073e845cfc3Masahiko Endo throw new SipException( 48325ccbb97ffd3298caede635f29445073e845cfc3Masahiko Endo "SipService.createSession() returns null"); 48425ccbb97ffd3298caede635f29445073e845cfc3Masahiko Endo } 485363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang session.register(expiryTime); 486363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } catch (RemoteException e) { 487363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new SipException("register()", e); 488363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 489363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 490363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 491363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 49284a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * Manually unregisters the profile from the corresponding SIP provider for 49384a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * stop receiving further calls. This may interference with the auto 49484a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * registration process in the SIP service if the auto-registration option 49584a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan * in the profile is enabled. 496363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 497363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param localProfile the SIP profile to register with 498363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param listener to listen to the registration events 499363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws SipException if calling the SIP service results in an error 500363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 501363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void unregister(SipProfile localProfile, 502363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang SipRegistrationListener listener) throws SipException { 503363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang try { 5049e1d308e993d451882456e44cfaacae63df7a496Hung-ying Tyan ISipSession session = mSipService.createSession(localProfile, 5059e1d308e993d451882456e44cfaacae63df7a496Hung-ying Tyan createRelay(listener, localProfile.getUriString())); 50625ccbb97ffd3298caede635f29445073e845cfc3Masahiko Endo if (session == null) { 50725ccbb97ffd3298caede635f29445073e845cfc3Masahiko Endo throw new SipException( 50825ccbb97ffd3298caede635f29445073e845cfc3Masahiko Endo "SipService.createSession() returns null"); 50925ccbb97ffd3298caede635f29445073e845cfc3Masahiko Endo } 510363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang session.unregister(); 511363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } catch (RemoteException e) { 512363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new SipException("unregister()", e); 513363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 514363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 515363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 516363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 51708faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * Gets the {@link SipSession} that handles the incoming call. For audio 518363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * calls, consider to use {@link SipAudioCall} to handle the incoming call. 519286bb5a00bdb9f0cb0815aef441ec72f231c84eaHung-ying Tyan * See {@link #takeAudioCall}. Note that the method may be called only once 520286bb5a00bdb9f0cb0815aef441ec72f231c84eaHung-ying Tyan * for the same intent. For subsequent calls on the same intent, the method 521286bb5a00bdb9f0cb0815aef441ec72f231c84eaHung-ying Tyan * returns null. 522363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 523363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param incomingCallIntent the incoming call broadcast intent 524363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @return the session object that handles the incoming call 525363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 52608faac3c26e12863858e1534985dd950193f755fHung-ying Tyan public SipSession getSessionFor(Intent incomingCallIntent) 527363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throws SipException { 528363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang try { 529363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang String callId = getCallId(incomingCallIntent); 53008faac3c26e12863858e1534985dd950193f755fHung-ying Tyan ISipSession s = mSipService.getPendingSession(callId); 53125ccbb97ffd3298caede635f29445073e845cfc3Masahiko Endo return ((s == null) ? null : new SipSession(s)); 532363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } catch (RemoteException e) { 533363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new SipException("getSessionFor()", e); 534363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 535363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 536363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 537363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private static ISipSessionListener createRelay( 5389e1d308e993d451882456e44cfaacae63df7a496Hung-ying Tyan SipRegistrationListener listener, String uri) { 5399e1d308e993d451882456e44cfaacae63df7a496Hung-ying Tyan return ((listener == null) ? null : new ListenerRelay(listener, uri)); 540363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 541363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 542363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 54308faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * Creates a {@link SipSession} with the specified profile. Use other 54408faac3c26e12863858e1534985dd950193f755fHung-ying Tyan * methods, if applicable, instead of interacting with {@link SipSession} 545363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * directly. 546363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 547363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param localProfile the SIP profile the session is associated with 548363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param listener to listen to SIP session events 549363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 55084a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan public SipSession createSipSession(SipProfile localProfile, 55184a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan SipSession.Listener listener) throws SipException { 552363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang try { 55384a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan ISipSession s = mSipService.createSession(localProfile, null); 5548d1b2a17d9935819ec96f1b5fca0e9945f564eaaHung-ying Tyan if (s == null) { 5558d1b2a17d9935819ec96f1b5fca0e9945f564eaaHung-ying Tyan throw new SipException( 5568d1b2a17d9935819ec96f1b5fca0e9945f564eaaHung-ying Tyan "Failed to create SipSession; network unavailable?"); 5578d1b2a17d9935819ec96f1b5fca0e9945f564eaaHung-ying Tyan } 55884a357bb6a8005e1c5e924e96a8ecf310e77c47cHung-ying Tyan return new SipSession(s, listener); 559363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } catch (RemoteException e) { 560363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new SipException("createSipSession()", e); 561363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 562363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 563363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 564363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 565363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Gets the list of profiles hosted by the SIP service. The user information 566363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * (username, password and display name) are crossed out. 567363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @hide 568363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 569363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public SipProfile[] getListOfProfiles() { 570363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang try { 571363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return mSipService.getListOfProfiles(); 572363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } catch (RemoteException e) { 5738d1b2a17d9935819ec96f1b5fca0e9945f564eaaHung-ying Tyan return new SipProfile[0]; 574363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 575363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 576363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 577363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private static class ListenerRelay extends SipSessionAdapter { 578363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private SipRegistrationListener mListener; 5799e1d308e993d451882456e44cfaacae63df7a496Hung-ying Tyan private String mUri; 580363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 581363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang // listener must not be null 5829e1d308e993d451882456e44cfaacae63df7a496Hung-ying Tyan public ListenerRelay(SipRegistrationListener listener, String uri) { 583363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mListener = listener; 5849e1d308e993d451882456e44cfaacae63df7a496Hung-ying Tyan mUri = uri; 585363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 586363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 587363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private String getUri(ISipSession session) { 588363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang try { 589fb3a98b1d8d0ad040980d509c4c5341928b9460bHung-ying Tyan return ((session == null) 5909e1d308e993d451882456e44cfaacae63df7a496Hung-ying Tyan ? mUri 591fb3a98b1d8d0ad040980d509c4c5341928b9460bHung-ying Tyan : session.getLocalProfile().getUriString()); 5929ea96c6cade1f25d4d77dcbd24854df431548b36Hung-ying Tyan } catch (Throwable e) { 5939ea96c6cade1f25d4d77dcbd24854df431548b36Hung-ying Tyan // SipService died? SIP stack died? 5949ea96c6cade1f25d4d77dcbd24854df431548b36Hung-ying Tyan Log.w(TAG, "getUri(): " + e); 5959ea96c6cade1f25d4d77dcbd24854df431548b36Hung-ying Tyan return null; 596363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 597363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 598363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 599363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang @Override 600363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void onRegistering(ISipSession session) { 601363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mListener.onRegistering(getUri(session)); 602363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 603363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 604363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang @Override 605363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void onRegistrationDone(ISipSession session, int duration) { 606363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang long expiryTime = duration; 607363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (duration > 0) expiryTime += System.currentTimeMillis(); 608363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mListener.onRegistrationDone(getUri(session), expiryTime); 609363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 610363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 611363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang @Override 61297963794af1e18674dd111e3ad344d90b16c922cHung-ying Tyan public void onRegistrationFailed(ISipSession session, int errorCode, 613363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang String message) { 61497963794af1e18674dd111e3ad344d90b16c922cHung-ying Tyan mListener.onRegistrationFailed(getUri(session), errorCode, message); 615363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 616363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 617363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang @Override 618363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void onRegistrationTimeout(ISipSession session) { 619363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mListener.onRegistrationFailed(getUri(session), 62099bf4e45c4566172189735b34b368b76660ca57aHung-ying Tyan SipErrorCode.TIME_OUT, "registration timed out"); 621363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 622363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 623363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang} 624