SipManager.java revision 1ab079168ccc185408a8691c6b804021d79f7376
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
3198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * allows the application to:
3298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * <ul>
3398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * <li>register a {@link SipProfile} to have the background SIP service listen
3498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *      to incoming calls and broadcast them with registered command string. See
3598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *      {@link #open(SipProfile, String, SipRegistrationListener)},
3698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *      {@link #open(SipProfile)}, {@link #close(String)},
3798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *      {@link #isOpened(String)} and {@link isRegistered(String)}. It also
3898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *      facilitates handling of the incoming call broadcast intent. See
3998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *      {@link #isIncomingCallIntent(Intent)}, {@link #getCallId(Intent)},
4098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *      {@link #getOfferSessionDescription(Intent)} and
4198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *      {@link #takeAudioCall(Context, Intent, SipAudioCall.Listener)}.</li>
4298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * <li>make/take SIP-based audio calls. See
4398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *      {@link #makeAudioCall(Context, SipProfile, SipProfile, SipAudioCall.Listener)}
4498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *      and {@link #takeAudioCall(Context, Intent, SipAudioCall.Listener}.</li>
4598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * <li>register/unregister with a SIP service provider. See
4698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *      {@link #register(SipProfile, int, ISipSessionListener)} and
4798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *      {@link #unregister(SipProfile, ISipSessionListener)}.</li>
4898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * <li>process SIP events directly with a {@link ISipSession} created by
4998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang *      {@link createSipSession(SipProfile, ISipSessionListener)}.</li>
5098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * </ul>
5198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @hide
5298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */
5398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangpublic class SipManager {
5498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /** @hide */
5598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public static final String SIP_INCOMING_CALL_ACTION =
5698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            "com.android.phone.SIP_INCOMING_CALL";
5798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /** @hide */
5898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public static final String SIP_ADD_PHONE_ACTION =
5998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            "com.android.phone.SIP_ADD_PHONE";
6098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /** @hide */
6198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public static final String SIP_REMOVE_PHONE_ACTION =
6298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            "com.android.phone.SIP_REMOVE_PHONE";
6398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /** @hide */
6498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public static final String LOCAL_URI_KEY = "LOCAL SIPURI";
6598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
6698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    private static final String CALL_ID_KEY = "CallID";
6798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    private static final String OFFER_SD_KEY = "OfferSD";
6898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
6998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    private ISipService mSipService;
7098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
7198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
7269d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan     * Gets a manager instance. Returns null if SIP API is not supported.
7398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
7469d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan     * @param context application context for checking if SIP API is supported
7569d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan     * @return the manager instance or null if SIP API is not supported
7698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
7769d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan    public static SipManager getInstance(Context context) {
7869d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan        return (isApiSupported(context) ? new SipManager() : null);
7969d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan    }
8069d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan
8169d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan    /**
8269d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan     * Returns true if the SIP API is supported by the system.
8369d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan     */
8469d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan    public static boolean isApiSupported(Context context) {
850d889a979d7e2e6f21de72de0c45a9c8ffa930e6Hung-ying Tyan        return true;
860d889a979d7e2e6f21de72de0c45a9c8ffa930e6Hung-ying Tyan        /*
8769d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan        return context.getPackageManager().hasSystemFeature(
8869d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan                PackageManager.FEATURE_SIP);
890d889a979d7e2e6f21de72de0c45a9c8ffa930e6Hung-ying Tyan         */
9069d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan    }
9169d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan
9269d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan    /**
9369d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan     * Returns true if the system supports SIP-based VoIP.
9469d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan     */
9569d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan    public static boolean isVoipSupported(Context context) {
960d889a979d7e2e6f21de72de0c45a9c8ffa930e6Hung-ying Tyan        return true;
970d889a979d7e2e6f21de72de0c45a9c8ffa930e6Hung-ying Tyan        /*
9869d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan        return context.getPackageManager().hasSystemFeature(
9969d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan                PackageManager.FEATURE_SIP_VOIP) && isApiSupported(context);
1000d889a979d7e2e6f21de72de0c45a9c8ffa930e6Hung-ying Tyan         */
10198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
10298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
10398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    private SipManager() {
10469d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan        createSipService();
10598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
10698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
10769d66b75112e2763bf8bce718c22c7baa1efac7dHung-ying Tyan    private void createSipService() {
10898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        if (mSipService != null) return;
10968144a84e3cd43ba4f62c73dbd2ce9c74d50e1a6Chung-yih Wang        IBinder b = ServiceManager.getService(Context.SIP_SERVICE);
11098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        mSipService = ISipService.Stub.asInterface(b);
11198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
11298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
11398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
11498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Opens the profile for making calls and/or receiving calls. Subsequent
11598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * SIP calls can be made through the default phone UI. The caller may also
11698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * make subsequent calls through
11798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * {@link #makeAudioCall(Context, String, String, SipAudioCall.Listener)}.
11898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * If the receiving-call option is enabled in the profile, the SIP service
11998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * will register the profile to the corresponding server periodically in
12098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * order to receive calls from the server.
12198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
12298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfile the SIP profile to make calls from
12398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if the profile contains incorrect settings or
12498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *      calling the SIP service results in an error
12598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
12698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public void open(SipProfile localProfile) throws SipException {
12798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
12898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mSipService.open(localProfile);
12998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
13098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("open()", e);
13198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
13298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
13398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
13498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
13598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Opens the profile for making calls and/or receiving calls. Subsequent
13698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * SIP calls can be made through the default phone UI. The caller may also
13798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * make subsequent calls through
13898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * {@link #makeAudioCall(Context, String, String, SipAudioCall.Listener)}.
13998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * If the receiving-call option is enabled in the profile, the SIP service
14098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * will register the profile to the corresponding server periodically in
14198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * order to receive calls from the server.
14298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
14398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfile the SIP profile to receive incoming calls for
14498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param incomingCallBroadcastAction the action to be broadcast when an
14598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *      incoming call is received
14698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to registration events; can be null
14798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if the profile contains incorrect settings or
14898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *      calling the SIP service results in an error
14998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
15098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public void open(SipProfile localProfile,
15198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            String incomingCallBroadcastAction,
15298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            SipRegistrationListener listener) throws SipException {
15398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
15498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mSipService.open3(localProfile, incomingCallBroadcastAction,
15598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                    createRelay(listener));
15698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
15798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("open()", e);
15898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
15998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
16098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
16198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
16298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Sets the listener to listen to registration events. No effect if the
16398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * profile has not been opened to receive calls
16498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * (see {@link #open(SipProfile, String, SipRegistrationListener)} and
16598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * {@link #open(SipProfile)}).
16698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
16798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfileUri the URI of the profile
16898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to registration events; can be null
16998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
17098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
17198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public void setRegistrationListener(String localProfileUri,
17298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            SipRegistrationListener listener) throws SipException {
17398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
17498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mSipService.setRegistrationListener(
17598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                    localProfileUri, createRelay(listener));
17698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
17798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("setRegistrationListener()", e);
17898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
17998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
18098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
18198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
18298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Closes the specified profile to not make/receive calls. All the resources
18398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * that were allocated to the profile are also released.
18498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
18598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfileUri the URI of the profile to close
18698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
18798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
18898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public void close(String localProfileUri) throws SipException {
18998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
19098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mSipService.close(localProfileUri);
19198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
19298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("close()", e);
19398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
19498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
19598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
19698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
19798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Checks if the specified profile is enabled to receive calls.
19898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
19998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfileUri the URI of the profile in question
20098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return true if the profile is enabled to receive calls
20198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
20298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
20398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public boolean isOpened(String localProfileUri) throws SipException {
20498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
20598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            return mSipService.isOpened(localProfileUri);
20698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
20798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("isOpened()", e);
20898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
20998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
21098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
21198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
21298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Checks if the specified profile is registered to the server for
21398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * receiving calls.
21498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
21598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfileUri the URI of the profile in question
21698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return true if the profile is registered to the server
21798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
21898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
21998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public boolean isRegistered(String localProfileUri) throws SipException {
22098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
22198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            return mSipService.isRegistered(localProfileUri);
22298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
22398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("isRegistered()", e);
22498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
22598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
22698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
22798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
22898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Creates a {@link SipAudioCall} to make a call.
22998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
23098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param context context to create a {@link SipAudioCall} object
23198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfile the SIP profile to make the call from
23298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param peerProfile the SIP profile to make the call to
23398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to the call events from {@link SipAudioCall};
23498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *      can be null
23598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return a {@link SipAudioCall} object
23698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
23798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
23898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public SipAudioCall makeAudioCall(Context context, SipProfile localProfile,
23998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            SipProfile peerProfile, SipAudioCall.Listener listener)
24098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throws SipException {
24198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        SipAudioCall call = new SipAudioCallImpl(context, localProfile);
24298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        call.setListener(listener);
24398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        call.makeCall(peerProfile, this);
24498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return call;
24598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
24698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
24798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
24898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Creates a {@link SipAudioCall} to make a call. To use this method, one
24998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * must call {@link #open(SipProfile)} first.
25098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
25198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param context context to create a {@link SipAudioCall} object
25298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfileUri URI of the SIP profile to make the call from
25398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param peerProfileUri URI of the SIP profile to make the call to
25498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to the call events from {@link SipAudioCall};
25598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *      can be null
25698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return a {@link SipAudioCall} object
25798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
25898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
25998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public SipAudioCall makeAudioCall(Context context, String localProfileUri,
26098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            String peerProfileUri, SipAudioCall.Listener listener)
26198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throws SipException {
26298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
26398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            return makeAudioCall(context,
26498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                    new SipProfile.Builder(localProfileUri).build(),
26598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                    new SipProfile.Builder(peerProfileUri).build(), listener);
26698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (ParseException e) {
26798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("build SipProfile", e);
26898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
26998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
27098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
27198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
27298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * The method calls {@code takeAudioCall(context, incomingCallIntent,
27398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * listener, true}.
27498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
27598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @see #takeAudioCall(Context, Intent, SipAudioCall.Listener, boolean)
27698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
27798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public SipAudioCall takeAudioCall(Context context,
27898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            Intent incomingCallIntent, SipAudioCall.Listener listener)
27998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throws SipException {
28098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return takeAudioCall(context, incomingCallIntent, listener, true);
28198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
28298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
28398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
28498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Creates a {@link SipAudioCall} to take an incoming call. Before the call
28598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * is returned, the listener will receive a
28698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * {@link SipAudioCall#Listener.onRinging(SipAudioCall, SipProfile)}
28798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * callback.
28898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
28998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param context context to create a {@link SipAudioCall} object
29098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param incomingCallIntent the incoming call broadcast intent
29198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to the call events from {@link SipAudioCall};
29298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *      can be null
29398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return a {@link SipAudioCall} object
29498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
29598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
29698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public SipAudioCall takeAudioCall(Context context,
29798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            Intent incomingCallIntent, SipAudioCall.Listener listener,
29898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            boolean ringtoneEnabled) throws SipException {
29998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        if (incomingCallIntent == null) return null;
30098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
30198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        String callId = getCallId(incomingCallIntent);
30298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        if (callId == null) {
30398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("Call ID missing in incoming call intent");
30498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
30598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
3066d0ef774a2492b0996ded3a43c300c7f72a94897Chia-chi Yeh        String offerSd = getOfferSessionDescription(incomingCallIntent);
30798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        if (offerSd == null) {
30898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("Session description missing in incoming "
30998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                    + "call intent");
31098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
31198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
31298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
31398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            ISipSession session = mSipService.getPendingSession(callId);
31498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            if (session == null) return null;
31598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            SipAudioCall call = new SipAudioCallImpl(
31698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                    context, session.getLocalProfile());
31798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            call.setRingtoneEnabled(ringtoneEnabled);
3186d0ef774a2492b0996ded3a43c300c7f72a94897Chia-chi Yeh            call.attachCall(session, offerSd);
31998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            call.setListener(listener);
32098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            return call;
32198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (Throwable t) {
32298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("takeAudioCall()", t);
32398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
32498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
32598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
32698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
32798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Checks if the intent is an incoming call broadcast intent.
32898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
32998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param intent the intent in question
33098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return true if the intent is an incoming call broadcast intent
33198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
33298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public static boolean isIncomingCallIntent(Intent intent) {
33398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        if (intent == null) return false;
33498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        String callId = getCallId(intent);
3356d0ef774a2492b0996ded3a43c300c7f72a94897Chia-chi Yeh        String offerSd = getOfferSessionDescription(intent);
33698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return ((callId != null) && (offerSd != null));
33798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
33898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
33998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
34098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Gets the call ID from the specified incoming call broadcast intent.
34198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
34298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param incomingCallIntent the incoming call broadcast intent
34398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return the call ID or null if the intent does not contain it
34498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
34598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public static String getCallId(Intent incomingCallIntent) {
34698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return incomingCallIntent.getStringExtra(CALL_ID_KEY);
34798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
34898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
34998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
35098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Gets the offer session description from the specified incoming call
35198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * broadcast intent.
35298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
35398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param incomingCallIntent the incoming call broadcast intent
35498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return the offer session description or null if the intent does not
35598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *      have it
35698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
3576d0ef774a2492b0996ded3a43c300c7f72a94897Chia-chi Yeh    public static String getOfferSessionDescription(Intent incomingCallIntent) {
3586d0ef774a2492b0996ded3a43c300c7f72a94897Chia-chi Yeh        return incomingCallIntent.getStringExtra(OFFER_SD_KEY);
35998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
36098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
36198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
36298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Creates an incoming call broadcast intent.
36398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
36498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param action the action string to broadcast
36598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param callId the call ID of the incoming call
36698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param sessionDescription the session description of the incoming call
36798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return the incoming call intent
36898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @hide
36998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
37098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public static Intent createIncomingCallBroadcast(String action,
3716d0ef774a2492b0996ded3a43c300c7f72a94897Chia-chi Yeh            String callId, String sessionDescription) {
37298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        Intent intent = new Intent(action);
37398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        intent.putExtra(CALL_ID_KEY, callId);
37498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        intent.putExtra(OFFER_SD_KEY, sessionDescription);
37598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return intent;
37698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
37798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
37898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
37998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Registers the profile to the corresponding server for receiving calls.
38098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * {@link #open(SipProfile, String, SipRegistrationListener)} is still
38198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * needed to be called at least once in order for the SIP service to
38298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * broadcast an intent when an incoming call is received.
38398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
38498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfile the SIP profile to register with
38598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param expiryTime registration expiration time (in second)
38698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to the registration events
38798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
38898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
38998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public void register(SipProfile localProfile, int expiryTime,
39098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            SipRegistrationListener listener) throws SipException {
39198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
39298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            ISipSession session = mSipService.createSession(
39398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                    localProfile, createRelay(listener));
39498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            session.register(expiryTime);
39598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
39698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("register()", e);
39798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
39898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
39998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
40098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
40198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Unregisters the profile from the corresponding server for not receiving
40298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * further calls.
40398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
40498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfile the SIP profile to register with
40598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to the registration events
40698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @throws SipException if calling the SIP service results in an error
40798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
40898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public void unregister(SipProfile localProfile,
40998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            SipRegistrationListener listener) throws SipException {
41098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
41198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            ISipSession session = mSipService.createSession(
41298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                    localProfile, createRelay(listener));
41398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            session.unregister();
41498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
41598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("unregister()", e);
41698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
41798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
41898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
41998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
42098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Gets the {@link ISipSession} that handles the incoming call. For audio
42198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * calls, consider to use {@link SipAudioCall} to handle the incoming call.
42298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * See {@link #takeAudioCall(Context, Intent, SipAudioCall.Listener)}.
42398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Note that the method may be called only once for the same intent. For
42498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * subsequent calls on the same intent, the method returns null.
42598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
42698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param incomingCallIntent the incoming call broadcast intent
42798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @return the session object that handles the incoming call
42898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
42998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public ISipSession getSessionFor(Intent incomingCallIntent)
43098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throws SipException {
43198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
43298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            String callId = getCallId(incomingCallIntent);
43398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            return mSipService.getPendingSession(callId);
43498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
43598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("getSessionFor()", e);
43698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
43798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
43898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
43998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    private static ISipSessionListener createRelay(
44098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            SipRegistrationListener listener) {
44198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        return ((listener == null) ? null : new ListenerRelay(listener));
44298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
44398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
44498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
44598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Creates a {@link ISipSession} with the specified profile. Use other
44698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * methods, if applicable, instead of interacting with {@link ISipSession}
44798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * directly.
44898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     *
44998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param localProfile the SIP profile the session is associated with
45098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @param listener to listen to SIP session events
45198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
45298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public ISipSession createSipSession(SipProfile localProfile,
45398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            ISipSessionListener listener) throws SipException {
45498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
45598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            return mSipService.createSession(localProfile, listener);
45698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
45798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            throw new SipException("createSipSession()", e);
45898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
45998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
46098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
46198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    /**
46298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * Gets the list of profiles hosted by the SIP service. The user information
46398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * (username, password and display name) are crossed out.
46498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     * @hide
46598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang     */
46698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    public SipProfile[] getListOfProfiles() {
46798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        try {
46898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            return mSipService.getListOfProfiles();
46998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        } catch (RemoteException e) {
47098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            return null;
47198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
47298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
47398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
47498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    private static class ListenerRelay extends SipSessionAdapter {
47598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        private SipRegistrationListener mListener;
47698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
47798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        // listener must not be null
47898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        public ListenerRelay(SipRegistrationListener listener) {
47998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mListener = listener;
48098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
48198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
48298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        private String getUri(ISipSession session) {
48398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            try {
48498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                return session.getLocalProfile().getUriString();
48598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            } catch (RemoteException e) {
48698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                throw new RuntimeException(e);
48798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            }
48898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
48998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
49098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        @Override
49198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        public void onRegistering(ISipSession session) {
49298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mListener.onRegistering(getUri(session));
49398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
49498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
49598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        @Override
49698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        public void onRegistrationDone(ISipSession session, int duration) {
49798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            long expiryTime = duration;
49898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            if (duration > 0) expiryTime += System.currentTimeMillis();
49998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mListener.onRegistrationDone(getUri(session), expiryTime);
50098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
50198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
50298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        @Override
503bba28d83647438df39b55d59161e3f69ff8209f6Hung-ying Tyan        public void onRegistrationFailed(ISipSession session, String errorCode,
50498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang                String message) {
5051ab079168ccc185408a8691c6b804021d79f7376Hung-ying Tyan            mListener.onRegistrationFailed(getUri(session),
5061ab079168ccc185408a8691c6b804021d79f7376Hung-ying Tyan                    Enum.valueOf(SipErrorCode.class, errorCode), message);
50798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
50898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang
50998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        @Override
51098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        public void onRegistrationTimeout(ISipSession session) {
51198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang            mListener.onRegistrationFailed(getUri(session),
5121ab079168ccc185408a8691c6b804021d79f7376Hung-ying Tyan                    SipErrorCode.TIME_OUT, "registration timed out");
51398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang        }
51498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang    }
51598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang}
516