SipManager.java revision d8d3b15f408314ac88201eee3e401a35556ba669
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
1998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport android.content.Context;
2098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport android.content.Intent;
2169d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyanimport android.content.pm.PackageManager;
2298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport android.os.IBinder;
2398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport android.os.Looper;
2498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport android.os.RemoteException;
2598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport android.os.ServiceManager;
2698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
2798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport java.text.ParseException;
2898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
2998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang/**
3098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * The class provides API for various SIP related tasks. Specifically, the API
31901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan * allows an application to:
3298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * <ul>
333adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * <li>open a {@link SipProfile} to get ready for making outbound calls or have
343adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan *      the background SIP service listen to incoming calls and broadcast them
353adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan *      with registered command string. See
3698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *      {@link #open(SipProfile, String, SipRegistrationListener)},
37901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan *      {@link #open(SipProfile)}, {@link #close}, {@link #isOpened} and
38901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan *      {@link #isRegistered}. It also facilitates handling of the incoming call
39901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan *      broadcast intent. See
40901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan *      {@link #isIncomingCallIntent}, {@link #getCallId},
41901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan *      {@link #getOfferSessionDescription} and {@link #takeAudioCall}.</li>
4298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * <li>make/take SIP-based audio calls. See
43901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan *      {@link #makeAudioCall} and {@link #takeAudioCall}.</li>
443adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * <li>register/unregister with a SIP service provider manually. See
45901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan *      {@link #register} and {@link #unregister}.</li>
463adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan * <li>process SIP events directly with a {@link SipSession} created by
47901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan *      {@link #createSipSession}.</li>
4898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * </ul>
4998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @hide
5098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */
5198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangpublic class SipManager {
523adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    /**
533adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * Action string for the incoming call intent for the Phone app.
543adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * Internal use only.
553adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * @hide
563adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     */
573adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    public static final String ACTION_SIP_INCOMING_CALL =
5898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            "com.android.phone.SIP_INCOMING_CALL";
593adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    /**
603adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * Action string for the add-phone intent.
613adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * Internal use only.
623adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * @hide
633adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     */
643adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    public static final String ACTION_SIP_ADD_PHONE =
6598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            "com.android.phone.SIP_ADD_PHONE";
663adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    /**
673adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * Action string for the remove-phone intent.
683adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * Internal use only.
693adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * @hide
703adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     */
713adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    public static final String ACTION_SIP_REMOVE_PHONE =
7298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            "com.android.phone.SIP_REMOVE_PHONE";
733adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    /**
743adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * Part of the ACTION_SIP_ADD_PHONE and ACTION_SIP_REMOVE_PHONE intents.
753adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * Internal use only.
763adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * @hide
773adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     */
783adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    public static final String EXTRA_LOCAL_URI = "android:localSipUri";
7998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
803adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    /** Part of the incoming call intent. */
813adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    public static final String EXTRA_CALL_ID = "android:sipCallID";
823adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan
833adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    /** Part of the incoming call intent. */
843adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    public static final String EXTRA_OFFER_SD = "android:sipOfferSD";
8598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
8698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    private ISipService mSipService;
873adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    private Context mContext;
8898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
8998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
903adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * Creates a manager instance. Returns null if SIP API is not supported.
9198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
923adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * @param context application context for creating the manager object
9369d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan     * @return the manager instance or null if SIP API is not supported
9498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
953adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    public static SipManager newInstance(Context context) {
963adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan        return (isApiSupported(context) ? new SipManager(context) : null);
9769d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan    }
9869d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan
9969d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan    /**
10069d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan     * Returns true if the SIP API is supported by the system.
10169d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan     */
10269d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan    public static boolean isApiSupported(Context context) {
1030d889a979d7e2e6f21de72de0c45a9c8ffa930e6Hung-ying Tyan        return true;
1043adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan        /* TODO: uncomment this before ship
10569d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan        return context.getPackageManager().hasSystemFeature(
10669d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan                PackageManager.FEATURE_SIP);
1070d889a979d7e2e6f21de72de0c45a9c8ffa930e6Hung-ying Tyan         */
10869d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan    }
10969d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan
11069d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan    /**
11169d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan     * Returns true if the system supports SIP-based VoIP.
11269d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan     */
11369d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan    public static boolean isVoipSupported(Context context) {
1140d889a979d7e2e6f21de72de0c45a9c8ffa930e6Hung-ying Tyan        return true;
1153adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan        /* TODO: uncomment this before ship
11669d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan        return context.getPackageManager().hasSystemFeature(
11769d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan                PackageManager.FEATURE_SIP_VOIP) && isApiSupported(context);
1180d889a979d7e2e6f21de72de0c45a9c8ffa930e6Hung-ying Tyan         */
11998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
12098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
121d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan    /**
122d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan     * Returns true if SIP is only available on WIFI.
123d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan     */
124d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan    public static boolean isSipWifiOnly(Context context) {
125d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan        return context.getResources().getBoolean(
126d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan                com.android.internal.R.bool.config_sip_wifi_only);
127d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan    }
128d96284491dfc918c72258f84b47a6554c21db92eHung-ying Tyan
1293adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    private SipManager(Context context) {
1303adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan        mContext = context;
13169d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan        createSipService();
13298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
13398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
13469d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan    private void createSipService() {
13568144a84e3cd43ba4f62c73dbd2ce9c74d50e1a6Chung-yih Wang        IBinder b = ServiceManager.getService(Context.SIP_SERVICE);
13698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        mSipService = ISipService.Stub.asInterface(b);
13798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
13898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
13998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
1403adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * Opens the profile for making calls. The caller may make subsequent calls
1413adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * through {@link #makeAudioCall}. If one also wants to receive calls on the
1423adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * profile, use {@link #open(SipProfile, String, SipRegistrationListener)}
1433adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * instead.
14498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
14598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfile the SIP profile to make calls from
14698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if the profile contains incorrect settings or
14798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *      calling the SIP service results in an error
14898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
14998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public void open(SipProfile localProfile) throws SipException {
15098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
15198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mSipService.open(localProfile);
15298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
15398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("open()", e);
15498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
15598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
15698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
15798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
1583adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * Opens the profile for making calls and/or receiving calls. The caller may
1593adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * make subsequent calls through {@link #makeAudioCall}. If the
1603adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * auto-registration option is enabled in the profile, the SIP service
1613adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * will register the profile to the corresponding SIP provider periodically
1623adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * in order to receive calls from the provider.
16398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
16498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfile the SIP profile to receive incoming calls for
16598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param incomingCallBroadcastAction the action to be broadcast when an
16698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *      incoming call is received
16798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to registration events; can be null
16898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if the profile contains incorrect settings or
16998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *      calling the SIP service results in an error
17098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
17198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public void open(SipProfile localProfile,
17298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            String incomingCallBroadcastAction,
17398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            SipRegistrationListener listener) throws SipException {
17498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
17598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mSipService.open3(localProfile, incomingCallBroadcastAction,
17698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                    createRelay(listener));
17798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
17898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("open()", e);
17998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
18098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
18198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
18298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
18398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Sets the listener to listen to registration events. No effect if the
184901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan     * profile has not been opened to receive calls (see {@link #open}).
18598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
18698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfileUri the URI of the profile
18798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to registration events; can be null
18898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
18998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
19098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public void setRegistrationListener(String localProfileUri,
19198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            SipRegistrationListener listener) throws SipException {
19298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
19398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mSipService.setRegistrationListener(
19498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                    localProfileUri, createRelay(listener));
19598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
19698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("setRegistrationListener()", e);
19798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
19898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
19998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
20098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
20198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Closes the specified profile to not make/receive calls. All the resources
20298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * that were allocated to the profile are also released.
20398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
20498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfileUri the URI of the profile to close
20598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
20698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
20798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public void close(String localProfileUri) throws SipException {
20898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
20998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mSipService.close(localProfileUri);
21098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
21198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("close()", e);
21298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
21398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
21498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
21598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
2163adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * Checks if the specified profile is opened in the SIP service for
2173adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * making and/or receiving calls.
21898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
21998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfileUri the URI of the profile in question
22098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return true if the profile is enabled to receive calls
22198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
22298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
22398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public boolean isOpened(String localProfileUri) throws SipException {
22498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
22598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            return mSipService.isOpened(localProfileUri);
22698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
22798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("isOpened()", e);
22898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
22998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
23098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
23198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
2323adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * Checks if the SIP service has successfully registered the profile to the
2333adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * SIP provider (specified in the profile) for receiving calls. Returning
2343adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * true from this method also implies the profile is opened
2353adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * ({@link #isOpened}).
23698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
23798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfileUri the URI of the profile in question
2383adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * @return true if the profile is registered to the SIP provider; false if
2393adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     *        the profile has not been opened in the SIP service or the SIP
2403adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     *        service has not yet successfully registered the profile to the SIP
2413adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     *        provider
24298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
24398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
24498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public boolean isRegistered(String localProfileUri) throws SipException {
24598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
24698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            return mSipService.isRegistered(localProfileUri);
24798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
24898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("isRegistered()", e);
24998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
25098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
25198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
25298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
253f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan     * Creates a {@link SipAudioCall} to make a call. The attempt will be timed
254f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan     * out if the call is not established within {@code timeout} seconds and
255f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan     * {@code SipAudioCall.Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
256f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan     * will be called.
25798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
25898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfile the SIP profile to make the call from
25998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param peerProfile the SIP profile to make the call to
26098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to the call events from {@link SipAudioCall};
26198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *      can be null
262f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan     * @param timeout the timeout value in seconds
26398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return a {@link SipAudioCall} object
26498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
265f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan     * @see SipAudioCall.Listener.onError
26698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
2673adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    public SipAudioCall makeAudioCall(SipProfile localProfile,
268f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan            SipProfile peerProfile, SipAudioCall.Listener listener, int timeout)
26998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throws SipException {
2703adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan        SipAudioCall call = new SipAudioCall(mContext, localProfile);
27198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        call.setListener(listener);
2727a4ec7268fbfb56e22f1cb8497d37ed733d8aa8eHung-ying Tyan        SipSession s = createSipSession(localProfile, null);
2737a4ec7268fbfb56e22f1cb8497d37ed733d8aa8eHung-ying Tyan        if (s == null) {
2747a4ec7268fbfb56e22f1cb8497d37ed733d8aa8eHung-ying Tyan            throw new SipException(
2757a4ec7268fbfb56e22f1cb8497d37ed733d8aa8eHung-ying Tyan                    "Failed to create SipSession; network available?");
2767a4ec7268fbfb56e22f1cb8497d37ed733d8aa8eHung-ying Tyan        }
2777a4ec7268fbfb56e22f1cb8497d37ed733d8aa8eHung-ying Tyan        call.makeCall(peerProfile, s, timeout);
27898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return call;
27998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
28098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
28198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
28298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Creates a {@link SipAudioCall} to make a call. To use this method, one
283f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan     * must call {@link #open(SipProfile)} first. The attempt will be timed out
284f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan     * if the call is not established within {@code timeout} seconds and
285f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan     * {@code SipAudioCall.Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
286f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan     * will be called.
28798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
28898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfileUri URI of the SIP profile to make the call from
28998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param peerProfileUri URI of the SIP profile to make the call to
29098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to the call events from {@link SipAudioCall};
29198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *      can be null
292f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan     * @param timeout the timeout value in seconds
29398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return a {@link SipAudioCall} object
29498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
295f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan     * @see SipAudioCall.Listener.onError
29698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
2973adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    public SipAudioCall makeAudioCall(String localProfileUri,
298f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan            String peerProfileUri, SipAudioCall.Listener listener, int timeout)
29998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throws SipException {
30098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
3013adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan            return makeAudioCall(
30298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                    new SipProfile.Builder(localProfileUri).build(),
303f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan                    new SipProfile.Builder(peerProfileUri).build(), listener,
304f498e98d2e2910e866ec0728cebbe676dd475d9eHung-ying Tyan                    timeout);
30598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (ParseException e) {
30698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("build SipProfile", e);
30798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
30898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
30998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
31098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
3113adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * The method calls {@code takeAudioCall(incomingCallIntent,
31298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * listener, true}.
31398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
3143adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * @see #takeAudioCall(Intent, SipAudioCall.Listener, boolean)
31598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
3163adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    public SipAudioCall takeAudioCall(Intent incomingCallIntent,
3173adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan            SipAudioCall.Listener listener) throws SipException {
3183adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan        return takeAudioCall(incomingCallIntent, listener, true);
31998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
32098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
32198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
32298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Creates a {@link SipAudioCall} to take an incoming call. Before the call
32398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * is returned, the listener will receive a
324901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan     * {@link SipAudioCall.Listener#onRinging}
32598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * callback.
32698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
32798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param incomingCallIntent the incoming call broadcast intent
32898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to the call events from {@link SipAudioCall};
32998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *      can be null
33098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return a {@link SipAudioCall} object
33198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
33298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
3333adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    public SipAudioCall takeAudioCall(Intent incomingCallIntent,
3343adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan            SipAudioCall.Listener listener, boolean ringtoneEnabled)
3353adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan            throws SipException {
33698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        if (incomingCallIntent == null) return null;
33798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
33898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        String callId = getCallId(incomingCallIntent);
33998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        if (callId == null) {
34098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("Call ID missing in incoming call intent");
34198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
34298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
3436d0ef774a2492b0996ded3a43c300c7f72a94897Chia-chi Yeh        String offerSd = getOfferSessionDescription(incomingCallIntent);
34498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        if (offerSd == null) {
34598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("Session description missing in incoming "
34698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                    + "call intent");
34798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
34898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
34998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
35098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            ISipSession session = mSipService.getPendingSession(callId);
35198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            if (session == null) return null;
3523adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan            SipAudioCall call = new SipAudioCall(
3533adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan                    mContext, session.getLocalProfile());
35498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            call.setRingtoneEnabled(ringtoneEnabled);
3553adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan            call.attachCall(new SipSession(session), offerSd);
35698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            call.setListener(listener);
35798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            return call;
35898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (Throwable t) {
35998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("takeAudioCall()", t);
36098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
36198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
36298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
36398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
36498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Checks if the intent is an incoming call broadcast intent.
36598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
36698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param intent the intent in question
36798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return true if the intent is an incoming call broadcast intent
36898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
36998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public static boolean isIncomingCallIntent(Intent intent) {
37098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        if (intent == null) return false;
37198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        String callId = getCallId(intent);
3726d0ef774a2492b0996ded3a43c300c7f72a94897Chia-chi Yeh        String offerSd = getOfferSessionDescription(intent);
37398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return ((callId != null) && (offerSd != null));
37498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
37598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
37698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
37798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Gets the call ID from the specified incoming call broadcast intent.
37898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
37998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param incomingCallIntent the incoming call broadcast intent
38098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return the call ID or null if the intent does not contain it
38198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
38298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public static String getCallId(Intent incomingCallIntent) {
3833adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan        return incomingCallIntent.getStringExtra(EXTRA_CALL_ID);
38498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
38598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
38698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
38798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Gets the offer session description from the specified incoming call
38898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * broadcast intent.
38998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
39098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param incomingCallIntent the incoming call broadcast intent
39198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return the offer session description or null if the intent does not
39298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *      have it
39398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
3946d0ef774a2492b0996ded3a43c300c7f72a94897Chia-chi Yeh    public static String getOfferSessionDescription(Intent incomingCallIntent) {
3953adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan        return incomingCallIntent.getStringExtra(EXTRA_OFFER_SD);
39698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
39798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
39898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
39998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Creates an incoming call broadcast intent.
40098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
40198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param callId the call ID of the incoming call
40298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param sessionDescription the session description of the incoming call
40398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return the incoming call intent
40498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @hide
40598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
4063adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    public static Intent createIncomingCallBroadcast(String callId,
4073adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan            String sessionDescription) {
4083adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan        Intent intent = new Intent();
4093adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan        intent.putExtra(EXTRA_CALL_ID, callId);
4103adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan        intent.putExtra(EXTRA_OFFER_SD, sessionDescription);
41198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return intent;
41298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
41398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
41498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
4153adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * Manually registers the profile to the corresponding SIP provider for
4163adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * receiving calls. {@link #open(SipProfile, String, SipRegistrationListener)}
4173adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * is still needed to be called at least once in order for the SIP service
4183adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * to broadcast an intent when an incoming call is received.
41998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
42098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfile the SIP profile to register with
421901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan     * @param expiryTime registration expiration time (in seconds)
42298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to the registration events
42398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
42498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
42598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public void register(SipProfile localProfile, int expiryTime,
42698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            SipRegistrationListener listener) throws SipException {
42798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
42898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            ISipSession session = mSipService.createSession(
42998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                    localProfile, createRelay(listener));
43098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            session.register(expiryTime);
43198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
43298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("register()", e);
43398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
43498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
43598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
43698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
4373adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * Manually unregisters the profile from the corresponding SIP provider for
4383adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * stop receiving further calls. This may interference with the auto
4393adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * registration process in the SIP service if the auto-registration option
4403adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan     * in the profile is enabled.
44198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
44298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfile the SIP profile to register with
44398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to the registration events
44498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
44598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
44698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public void unregister(SipProfile localProfile,
44798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            SipRegistrationListener listener) throws SipException {
44898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
44998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            ISipSession session = mSipService.createSession(
45098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                    localProfile, createRelay(listener));
45198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            session.unregister();
45298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
45398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("unregister()", e);
45498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
45598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
45698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
45798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
45898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Gets the {@link ISipSession} that handles the incoming call. For audio
45998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * calls, consider to use {@link SipAudioCall} to handle the incoming call.
460901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan     * See {@link #takeAudioCall}. Note that the method may be called only once
461901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan     * for the same intent. For subsequent calls on the same intent, the method
462901503e1cf8b6cfac1540a22c325eb5cdd879429Hung-ying Tyan     * returns null.
46398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
46498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param incomingCallIntent the incoming call broadcast intent
46598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return the session object that handles the incoming call
46698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
46798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public ISipSession getSessionFor(Intent incomingCallIntent)
46898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throws SipException {
46998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
47098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            String callId = getCallId(incomingCallIntent);
47198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            return mSipService.getPendingSession(callId);
47298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
47398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("getSessionFor()", e);
47498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
47598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
47698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
47798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    private static ISipSessionListener createRelay(
47898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            SipRegistrationListener listener) {
47998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return ((listener == null) ? null : new ListenerRelay(listener));
48098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
48198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
48298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
48398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Creates a {@link ISipSession} with the specified profile. Use other
48498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * methods, if applicable, instead of interacting with {@link ISipSession}
48598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * directly.
48698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
48798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfile the SIP profile the session is associated with
48898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to SIP session events
48998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
4903adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan    public SipSession createSipSession(SipProfile localProfile,
4913adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan            SipSession.Listener listener) throws SipException {
49298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
4933adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan            ISipSession s = mSipService.createSession(localProfile, null);
4943adf1946e78b52686fa5458e24645b05da57dc22Hung-ying Tyan            return new SipSession(s, listener);
49598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
49698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("createSipSession()", e);
49798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
49898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
49998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
50098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
50198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Gets the list of profiles hosted by the SIP service. The user information
50298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * (username, password and display name) are crossed out.
50398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @hide
50498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
50598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public SipProfile[] getListOfProfiles() {
50698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
50798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            return mSipService.getListOfProfiles();
50898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
50998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            return null;
51098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
51198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
51298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
51398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    private static class ListenerRelay extends SipSessionAdapter {
51498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        private SipRegistrationListener mListener;
51598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
51698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        // listener must not be null
51798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        public ListenerRelay(SipRegistrationListener listener) {
51898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mListener = listener;
51998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
52098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
52198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        private String getUri(ISipSession session) {
52298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            try {
523d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan                return ((session == null)
524d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan                        ? "no session"
525d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan                        : session.getLocalProfile().getUriString());
52698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            } catch (RemoteException e) {
52798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                throw new RuntimeException(e);
52898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            }
52998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
53098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
53198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        @Override
53298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        public void onRegistering(ISipSession session) {
53398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mListener.onRegistering(getUri(session));
53498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
53598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
53698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        @Override
53798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        public void onRegistrationDone(ISipSession session, int duration) {
53898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            long expiryTime = duration;
53998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            if (duration > 0) expiryTime += System.currentTimeMillis();
54098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mListener.onRegistrationDone(getUri(session), expiryTime);
54198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
54298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
54398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        @Override
544a0171082cfc4b860a82dcf5ebbd498b253f1032fHung-ying Tyan        public void onRegistrationFailed(ISipSession session, int errorCode,
54598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                String message) {
546a0171082cfc4b860a82dcf5ebbd498b253f1032fHung-ying Tyan            mListener.onRegistrationFailed(getUri(session), errorCode, message);
54798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
54898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
54998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        @Override
55098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        public void onRegistrationTimeout(ISipSession session) {
55198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mListener.onRegistrationFailed(getUri(session),
5521ab079168ccc185408a8691c6b804021d79f7376Hung-ying Tyan                    SipErrorCode.TIME_OUT, "registration timed out");
55398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
55498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
55598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang}
556