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