Home | History | Annotate | Download | only in sip
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.sip;
     18 
     19 import android.net.sip.ISipSession;
     20 import android.net.sip.ISipSessionListener;
     21 import android.net.sip.SipProfile;
     22 import android.os.DeadObjectException;
     23 import android.telephony.Rlog;
     24 
     25 /** Class to help safely run a callback in a different thread. */
     26 class SipSessionListenerProxy extends ISipSessionListener.Stub {
     27     private static final String TAG = "SipSessionListnerProxy";
     28 
     29     private ISipSessionListener mListener;
     30 
     31     public void setListener(ISipSessionListener listener) {
     32         mListener = listener;
     33     }
     34 
     35     public ISipSessionListener getListener() {
     36         return mListener;
     37     }
     38 
     39     private void proxy(Runnable runnable) {
     40         // One thread for each calling back.
     41         // Note: Guarantee ordering if the issue becomes important. Currently,
     42         // the chance of handling two callback events at a time is none.
     43         new Thread(runnable, "SipSessionCallbackThread").start();
     44     }
     45 
     46     @Override
     47     public void onCalling(final ISipSession session) {
     48         if (mListener == null) return;
     49         proxy(new Runnable() {
     50             @Override
     51             public void run() {
     52                 try {
     53                     mListener.onCalling(session);
     54                 } catch (Throwable t) {
     55                     handle(t, "onCalling()");
     56                 }
     57             }
     58         });
     59     }
     60 
     61     @Override
     62     public void onRinging(final ISipSession session, final SipProfile caller,
     63             final String sessionDescription) {
     64         if (mListener == null) return;
     65         proxy(new Runnable() {
     66             @Override
     67             public void run() {
     68                 try {
     69                     mListener.onRinging(session, caller, sessionDescription);
     70                 } catch (Throwable t) {
     71                     handle(t, "onRinging()");
     72                 }
     73             }
     74         });
     75     }
     76 
     77     @Override
     78     public void onRingingBack(final ISipSession session) {
     79         if (mListener == null) return;
     80         proxy(new Runnable() {
     81             @Override
     82             public void run() {
     83                 try {
     84                     mListener.onRingingBack(session);
     85                 } catch (Throwable t) {
     86                     handle(t, "onRingingBack()");
     87                 }
     88             }
     89         });
     90     }
     91 
     92     @Override
     93     public void onCallEstablished(final ISipSession session,
     94             final String sessionDescription) {
     95         if (mListener == null) return;
     96         proxy(new Runnable() {
     97             @Override
     98             public void run() {
     99                 try {
    100                     mListener.onCallEstablished(session, sessionDescription);
    101                 } catch (Throwable t) {
    102                     handle(t, "onCallEstablished()");
    103                 }
    104             }
    105         });
    106     }
    107 
    108     @Override
    109     public void onCallEnded(final ISipSession session) {
    110         if (mListener == null) return;
    111         proxy(new Runnable() {
    112             @Override
    113             public void run() {
    114                 try {
    115                     mListener.onCallEnded(session);
    116                 } catch (Throwable t) {
    117                     handle(t, "onCallEnded()");
    118                 }
    119             }
    120         });
    121     }
    122 
    123     @Override
    124     public void onCallTransferring(final ISipSession newSession,
    125             final String sessionDescription) {
    126         if (mListener == null) return;
    127         proxy(new Runnable() {
    128             @Override
    129             public void run() {
    130                 try {
    131                     mListener.onCallTransferring(newSession, sessionDescription);
    132                 } catch (Throwable t) {
    133                     handle(t, "onCallTransferring()");
    134                 }
    135             }
    136         });
    137     }
    138 
    139     @Override
    140     public void onCallBusy(final ISipSession session) {
    141         if (mListener == null) return;
    142         proxy(new Runnable() {
    143             @Override
    144             public void run() {
    145                 try {
    146                     mListener.onCallBusy(session);
    147                 } catch (Throwable t) {
    148                     handle(t, "onCallBusy()");
    149                 }
    150             }
    151         });
    152     }
    153 
    154     @Override
    155     public void onCallChangeFailed(final ISipSession session,
    156             final int errorCode, final String message) {
    157         if (mListener == null) return;
    158         proxy(new Runnable() {
    159             @Override
    160             public void run() {
    161                 try {
    162                     mListener.onCallChangeFailed(session, errorCode, message);
    163                 } catch (Throwable t) {
    164                     handle(t, "onCallChangeFailed()");
    165                 }
    166             }
    167         });
    168     }
    169 
    170     @Override
    171     public void onError(final ISipSession session, final int errorCode,
    172             final String message) {
    173         if (mListener == null) return;
    174         proxy(new Runnable() {
    175             @Override
    176             public void run() {
    177                 try {
    178                     mListener.onError(session, errorCode, message);
    179                 } catch (Throwable t) {
    180                     handle(t, "onError()");
    181                 }
    182             }
    183         });
    184     }
    185 
    186     @Override
    187     public void onRegistering(final ISipSession session) {
    188         if (mListener == null) return;
    189         proxy(new Runnable() {
    190             @Override
    191             public void run() {
    192                 try {
    193                     mListener.onRegistering(session);
    194                 } catch (Throwable t) {
    195                     handle(t, "onRegistering()");
    196                 }
    197             }
    198         });
    199     }
    200 
    201     @Override
    202     public void onRegistrationDone(final ISipSession session,
    203             final int duration) {
    204         if (mListener == null) return;
    205         proxy(new Runnable() {
    206             @Override
    207             public void run() {
    208                 try {
    209                     mListener.onRegistrationDone(session, duration);
    210                 } catch (Throwable t) {
    211                     handle(t, "onRegistrationDone()");
    212                 }
    213             }
    214         });
    215     }
    216 
    217     @Override
    218     public void onRegistrationFailed(final ISipSession session,
    219             final int errorCode, final String message) {
    220         if (mListener == null) return;
    221         proxy(new Runnable() {
    222             @Override
    223             public void run() {
    224                 try {
    225                     mListener.onRegistrationFailed(session, errorCode, message);
    226                 } catch (Throwable t) {
    227                     handle(t, "onRegistrationFailed()");
    228                 }
    229             }
    230         });
    231     }
    232 
    233     @Override
    234     public void onRegistrationTimeout(final ISipSession session) {
    235         if (mListener == null) return;
    236         proxy(new Runnable() {
    237             @Override
    238             public void run() {
    239                 try {
    240                     mListener.onRegistrationTimeout(session);
    241                 } catch (Throwable t) {
    242                     handle(t, "onRegistrationTimeout()");
    243                 }
    244             }
    245         });
    246     }
    247 
    248     private void handle(Throwable t, String message) {
    249         if (t instanceof DeadObjectException) {
    250             mListener = null;
    251             // This creates race but it's harmless. Just don't log the error
    252             // when it happens.
    253         } else if (mListener != null) {
    254             loge(message, t);
    255         }
    256     }
    257 
    258     private void log(String s) {
    259         Rlog.d(TAG, s);
    260     }
    261 
    262     private void loge(String s, Throwable t) {
    263         Rlog.e(TAG, s, t);
    264     }
    265 }
    266