Home | History | Annotate | Download | only in telephony
      1 /*
      2  * Copyright (C) 2016 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * 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, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 
     17 package com.googlecode.android_scripting.facade.telephony;
     18 
     19 import java.util.HashMap;
     20 import java.util.ArrayList;
     21 import java.util.List;
     22 import java.util.Set;
     23 
     24 import android.telecom.Call;
     25 import android.telecom.Call.Details;
     26 import android.telecom.CallAudioState;
     27 import android.telecom.Conference;
     28 import android.telecom.Connection;
     29 import android.telecom.ConnectionService;
     30 import android.telecom.InCallService;
     31 import android.telecom.Phone;
     32 import android.telecom.TelecomManager;
     33 import android.telecom.VideoProfile;
     34 import android.telecom.VideoProfile.CameraCapabilities;
     35 
     36 import com.googlecode.android_scripting.Log;
     37 
     38 import com.googlecode.android_scripting.facade.EventFacade;
     39 
     40 public class InCallServiceImpl extends InCallService {
     41 
     42     private static InCallServiceImpl sService = null;
     43 
     44     public static InCallServiceImpl getService() {
     45         return sService;
     46     }
     47 
     48     public static class CallListener {
     49 
     50         public static final int LISTEN_CALL_ADDED   = 1 << 0;
     51         public static final int LISTEN_CALL_REMOVED = 1 << 1;
     52         public static final int LISTEN_ALL = LISTEN_CALL_ADDED | LISTEN_CALL_REMOVED;
     53 
     54         private static int sListenedEvents = 0;
     55 
     56         public static void startListeningForEvent( int event ) {
     57             sListenedEvents |= event & LISTEN_ALL;
     58         }
     59 
     60         public static void stopListeningForEvent( int event ) {
     61             sListenedEvents &= ~(event & LISTEN_ALL);
     62         }
     63 
     64         public static void onCallAdded(String callId, Call call) {
     65             Log.d("CallListener:onCallAdded()");
     66             if ((sListenedEvents & LISTEN_CALL_ADDED)
     67                     == LISTEN_CALL_ADDED) {
     68                 servicePostEvent(TelephonyConstants.EventTelecomCallAdded,
     69                         new CallEvent<Call>(callId, call));
     70             }
     71         }
     72 
     73         public static void onCallRemoved(String callId, Call call) {
     74             Log.d("CallListener:onCallRemoved()");
     75             if ((sListenedEvents & LISTEN_CALL_REMOVED)
     76                     == LISTEN_CALL_REMOVED) {
     77                 servicePostEvent(TelephonyConstants.EventTelecomCallRemoved,
     78                         new CallEvent<Call>(callId, call));
     79             }
     80         }
     81     };
     82 
     83 
     84     private static Object mLock = new Object();
     85 
     86     // Provides a return value for getCallState when no call is active
     87     public static final int STATE_INVALID = -1;
     88 
     89     // Provides a return value for getCallQuality when input is invalid
     90     public static final int QUALITY_INVALID = -1;
     91 
     92     // Provides a return value for getAudioRoute when input is invalid
     93     public static final int INVALID_AUDIO_ROUTE = -1;
     94 
     95     public static final int VIDEO_STATE_AUDIO_ONLY = VideoProfile.STATE_AUDIO_ONLY;
     96 
     97     public static final int VIDEO_STATE_TX_ENABLED = VideoProfile.STATE_TX_ENABLED;
     98 
     99     public static final int VIDEO_STATE_RX_ENABLED = VideoProfile.STATE_RX_ENABLED;
    100 
    101     public static final int VIDEO_STATE_BIDIRECTIONAL = VideoProfile.STATE_BIDIRECTIONAL;
    102 
    103     public static final int VIDEO_STATE_TX_PAUSED =
    104             VideoProfile.STATE_TX_ENABLED | VideoProfile.STATE_PAUSED;
    105 
    106     public static final int VIDEO_STATE_RX_PAUSED =
    107             VideoProfile.STATE_RX_ENABLED | VideoProfile.STATE_PAUSED;
    108 
    109     public static final int VIDEO_STATE_BIDIRECTIONAL_PAUSED =
    110             VideoProfile.STATE_BIDIRECTIONAL | VideoProfile.STATE_PAUSED;
    111 
    112     // Container class to return the call ID along with the event
    113     public static class CallEvent<EventType> {
    114 
    115         private final String mCallId;
    116         private final EventType mEvent;
    117 
    118         CallEvent(String callId, EventType event) {
    119             mCallId = callId;
    120             mEvent = event;
    121         }
    122 
    123         public String getCallId() {
    124             return mCallId;
    125         }
    126 
    127         public EventType getEvent() {
    128             return mEvent;
    129         }
    130     }
    131 
    132     // Currently the same as a call event... here for future use
    133     public static class VideoCallEvent<EventType> extends CallEvent<EventType> {
    134         VideoCallEvent(String callId, EventType event) {
    135             super(callId, event);
    136         }
    137     }
    138 
    139     private class CallCallback extends Call.Callback {
    140 
    141         // Invalid video state (valid >= 0)
    142         public static final int STATE_INVALID = InCallServiceImpl.STATE_INVALID;
    143 
    144         public static final int EVENT_INVALID = -1;
    145         public static final int EVENT_NONE = 0;
    146         public static final int EVENT_STATE_CHANGED = 1 << 0;
    147         public static final int EVENT_PARENT_CHANGED = 1 << 1;
    148         public static final int EVENT_CHILDREN_CHANGED = 1 << 2;
    149         public static final int EVENT_DETAILS_CHANGED = 1 << 3;
    150         public static final int EVENT_CANNED_TEXT_RESPONSES_LOADED = 1 << 4;
    151         public static final int EVENT_POST_DIAL_WAIT = 1 << 5;
    152         public static final int EVENT_VIDEO_CALL_CHANGED = 1 << 6;
    153         public static final int EVENT_CALL_DESTROYED = 1 << 7;
    154         public static final int EVENT_CONFERENCABLE_CALLS_CHANGED = 1 << 8;
    155 
    156         public static final int EVENT_ALL = EVENT_STATE_CHANGED |
    157                 EVENT_PARENT_CHANGED |
    158                 EVENT_CHILDREN_CHANGED |
    159                 EVENT_DETAILS_CHANGED |
    160                 EVENT_CANNED_TEXT_RESPONSES_LOADED |
    161                 EVENT_POST_DIAL_WAIT |
    162                 EVENT_VIDEO_CALL_CHANGED |
    163                 EVENT_DETAILS_CHANGED |
    164                 EVENT_CALL_DESTROYED |
    165                 EVENT_CONFERENCABLE_CALLS_CHANGED;
    166 
    167         private int mEvents;
    168         private String mCallId;
    169 
    170         public CallCallback(String callId, int events) {
    171             super();
    172             mEvents = events & EVENT_ALL;
    173             mCallId = callId;
    174         }
    175 
    176         public void startListeningForEvents(int events) {
    177             mEvents |= events & EVENT_ALL;
    178         }
    179 
    180         public void stopListeningForEvents(int events) {
    181             mEvents &= ~(events & EVENT_ALL);
    182         }
    183 
    184         @Override
    185         public void onStateChanged(
    186                 Call call, int state) {
    187             Log.d("CallCallback:onStateChanged()");
    188             if ((mEvents & EVENT_STATE_CHANGED)
    189                     == EVENT_STATE_CHANGED) {
    190                 servicePostEvent(TelephonyConstants.EventTelecomCallStateChanged,
    191                         new CallEvent<String>(mCallId, getCallStateString(state)));
    192             }
    193         }
    194 
    195         @Override
    196         public void onParentChanged(
    197                 Call call, Call parent) {
    198             Log.d("CallCallback:onParentChanged()");
    199             if ((mEvents & EVENT_PARENT_CHANGED)
    200                     == EVENT_PARENT_CHANGED) {
    201                 servicePostEvent(TelephonyConstants.EventTelecomCallParentChanged,
    202                         new CallEvent<String>(mCallId, getCallId(parent)));
    203             }
    204         }
    205 
    206         @Override
    207         public void onChildrenChanged(
    208                 Call call, List<Call> children) {
    209             Log.d("CallCallback:onChildrenChanged()");
    210 
    211             if ((mEvents & EVENT_CHILDREN_CHANGED)
    212                     == EVENT_CHILDREN_CHANGED) {
    213                 List<String> childList = new ArrayList<String>();
    214 
    215                 for (Call child : children) {
    216                     childList.add(getCallId(child));
    217                 }
    218                 servicePostEvent(TelephonyConstants.EventTelecomCallChildrenChanged,
    219                         new CallEvent<List<String>>(mCallId, childList));
    220             }
    221         }
    222 
    223         @Override
    224         public void onDetailsChanged(
    225                 Call call, Details details) {
    226             Log.d("CallCallback:onDetailsChanged()");
    227 
    228             if ((mEvents & EVENT_DETAILS_CHANGED)
    229                     == EVENT_DETAILS_CHANGED) {
    230                 servicePostEvent(TelephonyConstants.EventTelecomCallDetailsChanged,
    231                         new CallEvent<Details>(mCallId, details));
    232             }
    233         }
    234 
    235         @Override
    236         public void onCannedTextResponsesLoaded(
    237                 Call call, List<String> cannedTextResponses) {
    238             Log.d("CallCallback:onCannedTextResponsesLoaded()");
    239             if ((mEvents & EVENT_CANNED_TEXT_RESPONSES_LOADED)
    240                     == EVENT_CANNED_TEXT_RESPONSES_LOADED) {
    241                 servicePostEvent(TelephonyConstants.EventTelecomCallCannedTextResponsesLoaded,
    242                         new CallEvent<List<String>>(mCallId, cannedTextResponses));
    243             }
    244         }
    245 
    246         @Override
    247         public void onPostDialWait(
    248                 Call call, String remainingPostDialSequence) {
    249             Log.d("CallCallback:onPostDialWait()");
    250             if ((mEvents & EVENT_POST_DIAL_WAIT)
    251                     == EVENT_POST_DIAL_WAIT) {
    252                 servicePostEvent(TelephonyConstants.EventTelecomCallPostDialWait,
    253                         new CallEvent<String>(mCallId, remainingPostDialSequence));
    254             }
    255         }
    256 
    257         @Override
    258         public void onVideoCallChanged(
    259                 Call call, InCallService.VideoCall videoCall) {
    260 
    261             /*
    262              * There is a race condition such that the lifetime of the VideoCall is not aligned with
    263              * the lifetime of the underlying call object. We are using the onVideoCallChanged
    264              * method as a way of determining the lifetime of the VideoCall object rather than
    265              * onCallAdded/onCallRemoved.
    266              */
    267             Log.d("CallCallback:onVideoCallChanged()");
    268 
    269             if (call != null) {
    270                 String callId = getCallId(call);
    271                 CallContainer cc = mCallContainerMap.get(callId);
    272                 if (cc == null) {
    273                     Log.d(String.format("Call container returned null for callId %s", callId));
    274                 }
    275                 else {
    276                     synchronized (mLock) {
    277                         if (videoCall == null) {
    278                             Log.d("Yo dawg, I heard you like null video calls.");
    279                             // Try and see if the videoCall has been added/changed after firing the
    280                             // callback
    281                             // This probably won't work.
    282                             videoCall = call.getVideoCall();
    283                         }
    284                         if (cc.getVideoCall() != videoCall) {
    285                             if (videoCall == null) {
    286                                 // VideoCall object deleted
    287                                 cc.updateVideoCall(null, null);
    288                                 Log.d("Removing video call from call.");
    289                             }
    290                             else if (cc.getVideoCall() != null) {
    291                                 // Somehow we have a mismatched VideoCall ID!
    292                                 Log.d("Mismatched video calls for same call ID.");
    293                             }
    294                             else {
    295                                 Log.d("Huzzah, we have a video call!");
    296 
    297                                 VideoCallCallback videoCallCallback =
    298                                         new VideoCallCallback(callId, VideoCallCallback.EVENT_NONE);
    299 
    300                                 videoCall.registerCallback(videoCallCallback);
    301 
    302                                 cc.updateVideoCall(
    303                                         videoCall,
    304                                         videoCallCallback);
    305                             }
    306                         }
    307                         else {
    308                             Log.d("Change to existing video call.");
    309                         }
    310 
    311                     }
    312                 }
    313             }
    314             else {
    315                 Log.d("passed null call pointer to call callback");
    316             }
    317 
    318             if ((mEvents & EVENT_VIDEO_CALL_CHANGED)
    319                     == EVENT_VIDEO_CALL_CHANGED) {
    320                 // TODO: b/26273778 Need to determine what to return;
    321                 // probably not the whole video call
    322                 servicePostEvent(TelephonyConstants.EventTelecomCallVideoCallChanged,
    323                         new CallEvent<String>(mCallId, videoCall.toString()));
    324             }
    325         }
    326 
    327         @Override
    328         public void onCallDestroyed(Call call) {
    329             Log.d("CallCallback:onCallDestroyed()");
    330 
    331             if ((mEvents & EVENT_CALL_DESTROYED)
    332                     == EVENT_CALL_DESTROYED) {
    333                 servicePostEvent(TelephonyConstants.EventTelecomCallDestroyed,
    334                         new CallEvent<Call>(mCallId, call));
    335             }
    336         }
    337 
    338         @Override
    339         public void onConferenceableCallsChanged(
    340                 Call call, List<Call> conferenceableCalls) {
    341             Log.d("CallCallback:onConferenceableCallsChanged()");
    342 
    343             if ((mEvents & EVENT_CONFERENCABLE_CALLS_CHANGED)
    344                     == EVENT_CONFERENCABLE_CALLS_CHANGED) {
    345                 List<String> confCallList = new ArrayList<String>();
    346                 for (Call cc : conferenceableCalls) {
    347                     confCallList.add(getCallId(cc));
    348                 }
    349                 servicePostEvent(TelephonyConstants.EventTelecomCallConferenceableCallsChanged,
    350                         new CallEvent<List<String>>(mCallId, confCallList));
    351             }
    352         }
    353     }
    354 
    355     private class VideoCallCallback extends InCallService.VideoCall.Callback {
    356 
    357         public static final int EVENT_INVALID = -1;
    358         public static final int EVENT_NONE = 0;
    359         public static final int EVENT_SESSION_MODIFY_REQUEST_RECEIVED = 1 << 0;
    360         public static final int EVENT_SESSION_MODIFY_RESPONSE_RECEIVED = 1 << 1;
    361         public static final int EVENT_SESSION_EVENT = 1 << 2;
    362         public static final int EVENT_PEER_DIMENSIONS_CHANGED = 1 << 3;
    363         public static final int EVENT_VIDEO_QUALITY_CHANGED = 1 << 4;
    364         public static final int EVENT_DATA_USAGE_CHANGED = 1 << 5;
    365         public static final int EVENT_CAMERA_CAPABILITIES_CHANGED = 1 << 6;
    366         public static final int EVENT_ALL =
    367                 EVENT_SESSION_MODIFY_REQUEST_RECEIVED |
    368                 EVENT_SESSION_MODIFY_RESPONSE_RECEIVED |
    369                 EVENT_SESSION_EVENT |
    370                 EVENT_PEER_DIMENSIONS_CHANGED |
    371                 EVENT_VIDEO_QUALITY_CHANGED |
    372                 EVENT_DATA_USAGE_CHANGED |
    373                 EVENT_CAMERA_CAPABILITIES_CHANGED;
    374 
    375         private String mCallId;
    376         private int mEvents;
    377 
    378         public VideoCallCallback(String callId, int listeners) {
    379 
    380             mCallId = callId;
    381             mEvents = listeners & EVENT_ALL;
    382         }
    383 
    384         public void startListeningForEvents(int events) {
    385             Log.d(String.format(
    386                     "VideoCallCallback(%s):startListeningForEvents(%x): events:%x",
    387                     mCallId, events, mEvents));
    388 
    389             mEvents |= events & EVENT_ALL;
    390 
    391         }
    392 
    393         public void stopListeningForEvents(int events) {
    394             mEvents &= ~(events & EVENT_ALL);
    395         }
    396 
    397         @Override
    398         public void onSessionModifyRequestReceived(VideoProfile videoProfile) {
    399             Log.d(String.format("VideoCallCallback(%s):onSessionModifyRequestReceived()", mCallId));
    400 
    401             if ((mEvents & EVENT_SESSION_MODIFY_REQUEST_RECEIVED)
    402                     == EVENT_SESSION_MODIFY_REQUEST_RECEIVED) {
    403                 servicePostEvent(TelephonyConstants.EventTelecomVideoCallSessionModifyRequestReceived,
    404                         new VideoCallEvent<VideoProfile>(mCallId, videoProfile));
    405             }
    406 
    407         }
    408 
    409         @Override
    410         public void onSessionModifyResponseReceived(int status,
    411                 VideoProfile requestedProfile, VideoProfile responseProfile) {
    412             Log.d("VideoCallCallback:onSessionModifyResponseReceived()");
    413 
    414             if ((mEvents & EVENT_SESSION_MODIFY_RESPONSE_RECEIVED)
    415                     == EVENT_SESSION_MODIFY_RESPONSE_RECEIVED) {
    416 
    417                 HashMap<String, VideoProfile> smrrInfo = new HashMap<String, VideoProfile>();
    418 
    419                 smrrInfo.put("RequestedProfile", requestedProfile);
    420                 smrrInfo.put("ResponseProfile", responseProfile);
    421 
    422                 servicePostEvent(TelephonyConstants.EventTelecomVideoCallSessionModifyResponseReceived,
    423                         new VideoCallEvent<HashMap<String, VideoProfile>>(mCallId, smrrInfo));
    424             }
    425         }
    426 
    427         @Override
    428         public void onCallSessionEvent(int event) {
    429             Log.d("VideoCallCallback:onCallSessionEvent()");
    430 
    431             String eventString = getVideoCallSessionEventString(event);
    432 
    433             if ((mEvents & EVENT_SESSION_EVENT)
    434                     == EVENT_SESSION_EVENT) {
    435                 servicePostEvent(TelephonyConstants.EventTelecomVideoCallSessionEvent,
    436                         new VideoCallEvent<String>(mCallId, eventString));
    437             }
    438         }
    439 
    440         @Override
    441         public void onPeerDimensionsChanged(int width, int height) {
    442             Log.d("VideoCallCallback:onPeerDimensionsChanged()");
    443 
    444             if ((mEvents & EVENT_PEER_DIMENSIONS_CHANGED)
    445                     == EVENT_PEER_DIMENSIONS_CHANGED) {
    446 
    447                 HashMap<String, Integer> temp = new HashMap<String, Integer>();
    448                 temp.put("Width", width);
    449                 temp.put("Height", height);
    450 
    451                 servicePostEvent(TelephonyConstants.EventTelecomVideoCallPeerDimensionsChanged,
    452                         new VideoCallEvent<HashMap<String, Integer>>(mCallId, temp));
    453             }
    454         }
    455 
    456         @Override
    457         public void onVideoQualityChanged(int videoQuality) {
    458             Log.d("VideoCallCallback:onVideoQualityChanged()");
    459 
    460             if ((mEvents & EVENT_VIDEO_QUALITY_CHANGED)
    461                     == EVENT_VIDEO_QUALITY_CHANGED) {
    462                 servicePostEvent(TelephonyConstants.EventTelecomVideoCallVideoQualityChanged,
    463                         new VideoCallEvent<String>(mCallId,
    464                                 getVideoCallQualityString(videoQuality)));
    465             }
    466         }
    467 
    468         @Override
    469         public void onCallDataUsageChanged(long dataUsage) {
    470             Log.d("VideoCallCallback:onCallDataUsageChanged()");
    471 
    472             if ((mEvents & EVENT_DATA_USAGE_CHANGED)
    473                     == EVENT_DATA_USAGE_CHANGED) {
    474                 servicePostEvent(TelephonyConstants.EventTelecomVideoCallDataUsageChanged,
    475                         new VideoCallEvent<Long>(mCallId, dataUsage));
    476             }
    477         }
    478 
    479         @Override
    480         public void onCameraCapabilitiesChanged(
    481                 CameraCapabilities cameraCapabilities) {
    482             Log.d("VideoCallCallback:onCallDataUsageChanged()");
    483 
    484             if ((mEvents & EVENT_DATA_USAGE_CHANGED)
    485                     == EVENT_DATA_USAGE_CHANGED) {
    486                 servicePostEvent(TelephonyConstants.EventTelecomVideoCallCameraCapabilities,
    487                         new VideoCallEvent<CameraCapabilities>(mCallId, cameraCapabilities));
    488             }
    489 
    490         }
    491     }
    492 
    493     /*
    494      * Container Class for Call and CallCallback Objects
    495      */
    496     private class CallContainer {
    497 
    498         /*
    499          * Call Container Members
    500          */
    501 
    502         private Call mCall;
    503         private CallCallback mCallCallback;
    504         private VideoCall mVideoCall;
    505         private VideoCallCallback mVideoCallCallback;
    506 
    507         /*
    508          * Call Container Functions
    509          */
    510 
    511         public CallContainer(Call call,
    512                 CallCallback callback,
    513                 VideoCall videoCall,
    514                 VideoCallCallback videoCallCallback) {
    515             mCall = call;
    516             mCallCallback = callback;
    517             mVideoCall = videoCall;
    518             mVideoCallCallback = videoCallCallback;
    519         }
    520 
    521         public Call getCall() {
    522             return mCall;
    523         }
    524 
    525         public CallCallback getCallback() {
    526             return mCallCallback;
    527         }
    528 
    529         public InCallService.VideoCall getVideoCall() {
    530             return mVideoCall;
    531         }
    532 
    533         public VideoCallCallback getVideoCallCallback() {
    534             return mVideoCallCallback;
    535         }
    536 
    537         public void updateVideoCall(VideoCall videoCall, VideoCallCallback videoCallCallback) {
    538             if (videoCall == null && videoCallCallback != null) {
    539                 Log.d("UpdateVideoCall: videoCall and videoCallCallback are null.");
    540                 return;
    541             }
    542             mVideoCall = videoCall;
    543             mVideoCallCallback = videoCallCallback;
    544         }
    545     }
    546 
    547     /*
    548      * TODO: b/26272583 Refactor so that these are instance members of the
    549      * incallservice. Then we can perform null checks using the design pattern
    550      * of the "manager" classes.
    551      */
    552 
    553     private static EventFacade mEventFacade = null;
    554     private static HashMap<String, CallContainer> mCallContainerMap =
    555             new HashMap<String, CallContainer>();
    556 
    557     @Override
    558     public void onCallAdded(Call call) {
    559         Log.d("onCallAdded: " + call.toString());
    560         String id = getCallId(call);
    561         Log.d("Adding " + id);
    562         CallCallback callCallback = new CallCallback(id, CallCallback.EVENT_NONE);
    563 
    564         call.registerCallback(callCallback);
    565 
    566         VideoCall videoCall = call.getVideoCall();
    567         VideoCallCallback videoCallCallback = null;
    568 
    569         if (videoCall != null) {
    570             synchronized (mLock) {
    571                 if (getVideoCallById(id) == null) {
    572                     videoCallCallback = new VideoCallCallback(id, VideoCallCallback.EVENT_NONE);
    573                     videoCall.registerCallback(videoCallCallback);
    574                 }
    575             }
    576         }
    577         else {
    578             // No valid video object
    579             Log.d("No Video Call provided to InCallService.");
    580         }
    581 
    582         mCallContainerMap.put(id,
    583                 new CallContainer(call,
    584                         callCallback,
    585                         videoCall,
    586                         videoCallCallback));
    587 
    588         /*
    589          * Once we have a call active, anchor the inCallService instance as a psuedo-singleton.
    590          * Because object lifetime is not guaranteed we shouldn't do this in the
    591          * constructor/destructor.
    592          */
    593         if (sService == null) {
    594             sService = this;
    595         }
    596         else if (sService != this) {
    597             Log.e("Multiple InCall Services Active in SL4A!");
    598         }
    599 
    600         CallListener.onCallAdded(id, call);
    601     }
    602 
    603     @Override
    604     public void onCallRemoved(Call call) {
    605         Log.d("onCallRemoved: " + call.toString());
    606         String id = getCallId(call);
    607         Log.d("Removing " + id);
    608 
    609         mCallContainerMap.remove(id);
    610 
    611         CallListener.onCallRemoved(id, call);
    612 
    613         if (mCallContainerMap.size() == 0) {
    614             sService = null;
    615         }
    616     }
    617 
    618     public static void setEventFacade(EventFacade facade) {
    619         Log.d(String.format("setEventFacade(): Settings SL4A event facade to %s",
    620                 (facade != null) ? facade.toString() : "null"));
    621         mEventFacade = facade;
    622     }
    623 
    624     private static boolean servicePostEvent(String eventName, Object event) {
    625 
    626         if (mEventFacade == null) {
    627             Log.d("servicePostEvent():SL4A eventFacade Is Null!!");
    628             return false;
    629         }
    630 
    631         mEventFacade.postEvent(eventName, event);
    632 
    633         return true;
    634     }
    635 
    636     public static String getCallId(Call call) {
    637         if (call != null) {
    638             return "Call:"+call.hashCode();
    639         }
    640         else
    641             return "";
    642     }
    643 
    644     public static String getVideoCallId(InCallServiceImpl.VideoCall videoCall) {
    645         if (videoCall != null)
    646             return "VideoCall:"+videoCall.hashCode();
    647         else
    648             return "";
    649     }
    650 
    651     private static Call getCallById(String callId) {
    652 
    653         CallContainer cc = mCallContainerMap.get(callId);
    654 
    655         if (cc != null) {
    656             return cc.getCall();
    657         }
    658 
    659         return null;
    660     }
    661 
    662     private static CallCallback getCallCallbackById(String callId) {
    663 
    664         CallContainer cc = mCallContainerMap.get(callId);
    665 
    666         if (cc != null) {
    667             return cc.getCallback();
    668         }
    669 
    670         return null;
    671     }
    672 
    673     private static InCallService.VideoCall getVideoCallById(String callId) {
    674 
    675         CallContainer cc = mCallContainerMap.get(callId);
    676 
    677         if (cc != null) {
    678             return cc.getVideoCall();
    679 
    680         }
    681 
    682         return null;
    683     }
    684 
    685     private static VideoCallCallback
    686             getVideoCallListenerById(String callId) {
    687 
    688         CallContainer cc = mCallContainerMap.get(callId);
    689 
    690         if (cc != null) {
    691             return cc.getVideoCallCallback();
    692         }
    693 
    694         return null;
    695     }
    696 
    697     /*
    698      * Public Call/Phone Functions
    699      */
    700 
    701     public static void callDisconnect(String callId) {
    702         Call c = getCallById(callId);
    703         if (c == null) {
    704             Log.d("callDisconnect: callId is null");
    705             return;
    706         }
    707 
    708         c.disconnect();
    709     }
    710 
    711     public static void holdCall(String callId) {
    712         Call c = getCallById(callId);
    713         if (c == null) {
    714             Log.d("holdCall: callId is null");
    715             return;
    716         }
    717         c.hold();
    718     }
    719 
    720     public static void mergeCallsInConference(String callId) {
    721         Call c = getCallById(callId);
    722         if (c == null) {
    723             Log.d("mergeCallsInConference: callId is null");
    724             return;
    725         }
    726         c.mergeConference();
    727     }
    728 
    729     public static void splitCallFromConf(String callId) {
    730         Call c = getCallById(callId);
    731         if (c == null) {
    732             Log.d("splitCallFromConf: callId is null");
    733             return;
    734         }
    735         c.splitFromConference();
    736     }
    737 
    738     public static void unholdCall(String callId) {
    739         Call c = getCallById(callId);
    740         if (c == null) {
    741             Log.d("unholdCall: callId is null");
    742             return;
    743         }
    744         c.unhold();
    745     }
    746 
    747     public static void joinCallsInConf(String callIdOne, String callIdTwo) {
    748         Call callOne = getCallById(callIdOne);
    749         Call callTwo = getCallById(callIdTwo);
    750 
    751         if (callOne == null || callTwo == null) {
    752             Log.d("joinCallsInConf: callOne or CallTwo is null");
    753             return;
    754         }
    755 
    756         callOne.conference(callTwo);
    757     }
    758 
    759     public static Set<String> getCallIdList() {
    760         return mCallContainerMap.keySet();
    761     }
    762 
    763     public static void clearCallList() {
    764         mCallContainerMap.clear();
    765     }
    766 
    767     public static String callGetState(String callId) {
    768         Call c = getCallById(callId);
    769         if (c == null) {
    770             return getCallStateString(STATE_INVALID);
    771         }
    772 
    773         return getCallStateString(c.getState());
    774     }
    775 
    776     public static Call.Details callGetDetails(String callId) {
    777         Call c = getCallById(callId);
    778         if (c == null) {
    779             Log.d(String.format("Couldn't find an active call with ID:%s", callId));
    780             return null;
    781         }
    782 
    783         return c.getDetails();
    784     }
    785 
    786     public static List<String> callGetCallProperties(String callId) {
    787         Call.Details details = callGetDetails(callId);
    788 
    789         if (details == null) {
    790             return null;
    791         }
    792 
    793         return getCallPropertiesString(details.getCallProperties());
    794     }
    795 
    796     public static List<String> callGetCallCapabilities(String callId) {
    797         Call.Details details = callGetDetails(callId);
    798 
    799         if (details == null) {
    800             return null;
    801         }
    802 
    803         return getCallCapabilitiesString(details.getCallCapabilities());
    804     }
    805 
    806     @SuppressWarnings("deprecation")
    807     public static void overrideProximitySensor(Boolean screenOn) {
    808         InCallServiceImpl svc = getService();
    809         if (svc == null) {
    810             Log.d("overrideProximitySensor: InCallServiceImpl is null.");
    811             return;
    812         }
    813 
    814         Phone phone = svc.getPhone();
    815         if (phone == null) {
    816             Log.d("overrideProximitySensor: phone is null.");
    817             return;
    818         }
    819 
    820         phone.setProximitySensorOff(screenOn);
    821     }
    822 
    823     public static CallAudioState serviceGetCallAudioState() {
    824         InCallServiceImpl svc = getService();
    825 
    826         if (svc != null) {
    827             return svc.getCallAudioState();
    828         }
    829         else {
    830             return null;
    831         }
    832     }
    833 
    834     // Wonky name due to conflict with internal function
    835     public static void serviceSetAudioRoute(String route) {
    836         InCallServiceImpl svc = getService();
    837 
    838         if (svc == null) {
    839             Log.d("serviceSetAudioRoute: InCallServiceImpl is null.");
    840             return;
    841         }
    842 
    843         int r = getAudioRoute(route);
    844 
    845         Log.d(String.format("Setting Audio Route to %s:%d", route, r));
    846 
    847         if (r == INVALID_AUDIO_ROUTE) {
    848             Log.d(String.format("Invalid Audio route %s:%d", route, r));
    849             return;
    850         }
    851         svc.setAudioRoute(r);
    852     }
    853 
    854     public static void callStartListeningForEvent(String callId, String strEvent) {
    855 
    856         CallCallback cl = getCallCallbackById(callId);
    857 
    858         if (cl == null) {
    859             Log.d("callStartListeningForEvent: CallCallback is null.");
    860             return;
    861         }
    862 
    863         int event = getCallCallbackEvent(strEvent);
    864 
    865         if (event == CallCallback.EVENT_INVALID) {
    866             Log.d("callStartListeningForEvent: event is invalid.");
    867             return;
    868         }
    869 
    870         cl.startListeningForEvents(event);
    871     }
    872 
    873     public static void callStopListeningForEvent(String callId, String strEvent) {
    874         CallCallback cl = getCallCallbackById(callId);
    875 
    876         if (cl == null) {
    877             Log.d("callStopListeningForEvent: CallCallback is null.");
    878             return;
    879         }
    880 
    881         int event = getCallCallbackEvent(strEvent);
    882 
    883         if (event == CallCallback.EVENT_INVALID) {
    884             Log.d("callStopListeningForEvent: event is invalid.");
    885             return;
    886         }
    887 
    888         cl.stopListeningForEvents(event);
    889     }
    890 
    891     public static void videoCallStartListeningForEvent(String callId, String strEvent) {
    892         VideoCallCallback cl = getVideoCallListenerById(callId);
    893 
    894         if (cl == null) {
    895             Log.d(String.format("Couldn't find a call with call id:%s", callId));
    896             return;
    897         }
    898 
    899         int event = getVideoCallCallbackEvent(strEvent);
    900 
    901         if (event == VideoCallCallback.EVENT_INVALID) {
    902             Log.d(String.format("Failed to find a valid event:[%s]", strEvent));
    903             return;
    904         }
    905 
    906         cl.startListeningForEvents(event);
    907     }
    908 
    909     public static void videoCallStopListeningForEvent(String callId, String strEvent) {
    910         VideoCallCallback cl = getVideoCallListenerById(callId);
    911 
    912         if (cl == null) {
    913             Log.d("videoCallStopListeningForEvent: CallCallback is null.");
    914             return;
    915         }
    916 
    917         int event = getVideoCallCallbackEvent(strEvent);
    918 
    919         if (event == VideoCallCallback.EVENT_INVALID) {
    920             Log.d("getVideoCallCallbackEvent: event is invalid.");
    921             return;
    922         }
    923 
    924         cl.stopListeningForEvents(event);
    925     }
    926 
    927     public static String videoCallGetState(String callId) {
    928         Call c = getCallById(callId);
    929 
    930         int state = CallCallback.STATE_INVALID;
    931 
    932         if (c == null) {
    933             Log.d("videoCallGetState: call is null.");
    934         }
    935         else {
    936             state = c.getDetails().getVideoState();
    937         }
    938 
    939         return getVideoCallStateString(state);
    940     }
    941 
    942     public static void videoCallSendSessionModifyRequest(
    943             String callId, String videoStateString, String videoQualityString) {
    944         VideoCall vc = getVideoCallById(callId);
    945 
    946         if (vc == null) {
    947             Log.d("Invalid video call for call ID");
    948             return;
    949         }
    950 
    951         int videoState = getVideoCallState(videoStateString);
    952         int videoQuality = getVideoCallQuality(videoQualityString);
    953 
    954         Log.d(String.format("Sending Modify request for %s:%d, %s:%d",
    955                 videoStateString, videoState, videoQualityString, videoQuality));
    956 
    957         if (videoState == CallCallback.STATE_INVALID ||
    958                 videoQuality == QUALITY_INVALID || videoQuality == VideoProfile.QUALITY_UNKNOWN) {
    959             Log.d("Invalid session modify request!");
    960             return;
    961         }
    962 
    963         vc.sendSessionModifyRequest(new VideoProfile(videoState, videoQuality));
    964     }
    965 
    966     public static void videoCallSendSessionModifyResponse(
    967             String callId, String videoStateString, String videoQualityString) {
    968         VideoCall vc = getVideoCallById(callId);
    969 
    970         if (vc == null) {
    971             Log.d("Invalid video call for call ID");
    972             return;
    973         }
    974 
    975         int videoState = getVideoCallState(videoStateString);
    976         int videoQuality = getVideoCallQuality(videoQualityString);
    977 
    978         Log.d(String.format("Sending Modify request for %s:%d, %s:%d",
    979                 videoStateString, videoState, videoQualityString, videoQuality));
    980 
    981         if (videoState == CallCallback.STATE_INVALID ||
    982                 videoQuality == QUALITY_INVALID || videoQuality == VideoProfile.QUALITY_UNKNOWN) {
    983             Log.d("Invalid session modify request!");
    984             return;
    985         }
    986 
    987         vc.sendSessionModifyResponse(new VideoProfile(videoState, videoQuality));
    988     }
    989 
    990     public static void callAnswer(String callId, String videoState) {
    991         Call c = getCallById(callId);
    992 
    993         if (c == null) {
    994             Log.d("callAnswer: call is null.");
    995         }
    996 
    997         int state = getVideoCallState(videoState);
    998 
    999         if (state == CallCallback.STATE_INVALID) {
   1000             Log.d("callAnswer: video state is invalid.");
   1001             state = VideoProfile.STATE_AUDIO_ONLY;
   1002         }
   1003 
   1004         c.answer(state);
   1005     }
   1006 
   1007     public static void callReject(String callId, String message) {
   1008         Call c = getCallById(callId);
   1009 
   1010         if (c == null) {
   1011             Log.d("callReject: call is null.");
   1012         }
   1013 
   1014         c.reject((message != null) ? true : false, message);
   1015     }
   1016 
   1017     public static String getCallParent(String callId) {
   1018         Call c = getCallById(callId);
   1019 
   1020         if (c == null) {
   1021             Log.d("getCallParent: call is null.");
   1022             return null;
   1023         }
   1024         Call callParent = c.getParent();
   1025         return getCallId(callParent);
   1026     }
   1027 
   1028     public static List<String> getCallChildren(String callId) {
   1029         Call c = getCallById(callId);
   1030 
   1031         if (c == null) {
   1032             Log.d("getCallChildren: call is null.");
   1033             return null;
   1034         }
   1035         List<String> childrenList = new ArrayList<String>();
   1036         List<Call> callChildren = c.getChildren();
   1037         for (Call call : callChildren) {
   1038             childrenList.add(getCallId(call));
   1039         }
   1040         return childrenList;
   1041     }
   1042 
   1043     public static void swapCallsInConference(String callId) {
   1044         Call c = getCallById(callId);
   1045         if (c == null) {
   1046             Log.d("swapCallsInConference: call is null.");
   1047             return;
   1048         }
   1049         c.swapConference();
   1050     }
   1051 
   1052     public static void callPlayDtmfTone(String callId, char digit) {
   1053         Call c = getCallById(callId);
   1054         if (c == null) {
   1055             Log.d("callPlayDtmfTone: call is null.");
   1056             return;
   1057         }
   1058         c.playDtmfTone(digit);
   1059     }
   1060 
   1061     public static void callStopDtmfTone(String callId) {
   1062         Call c = getCallById(callId);
   1063         if (c == null) {
   1064             Log.d("callStopDtmfTone: call is null.");
   1065             return;
   1066         }
   1067         c.stopDtmfTone();
   1068     }
   1069 
   1070     public static List<String> callGetCannedTextResponses(String callId) {
   1071         Call c = getCallById(callId);
   1072         if (c == null) {
   1073             return null;
   1074         }
   1075 
   1076         return c.getCannedTextResponses();
   1077     }
   1078 
   1079     /*
   1080      * String Mapping Functions for Facade Parameter Translation
   1081      */
   1082 
   1083     public static String getVideoCallStateString(int state) {
   1084         switch (state) {
   1085             case VIDEO_STATE_AUDIO_ONLY:
   1086                 return TelephonyConstants.VT_STATE_AUDIO_ONLY;
   1087             case VIDEO_STATE_TX_ENABLED:
   1088                 return TelephonyConstants.VT_STATE_TX_ENABLED;
   1089             case VIDEO_STATE_RX_ENABLED:
   1090                 return TelephonyConstants.VT_STATE_RX_ENABLED;
   1091             case VIDEO_STATE_BIDIRECTIONAL:
   1092                 return TelephonyConstants.VT_STATE_BIDIRECTIONAL;
   1093             case VIDEO_STATE_TX_PAUSED:
   1094                 return TelephonyConstants.VT_STATE_TX_PAUSED;
   1095             case VIDEO_STATE_RX_PAUSED:
   1096                 return TelephonyConstants.VT_STATE_RX_PAUSED;
   1097             case VIDEO_STATE_BIDIRECTIONAL_PAUSED:
   1098                 return TelephonyConstants.VT_STATE_BIDIRECTIONAL_PAUSED;
   1099             default:
   1100         }
   1101         Log.d("getVideoCallStateString: state is invalid.");
   1102         return TelephonyConstants.VT_STATE_STATE_INVALID;
   1103     }
   1104 
   1105     public static int getVideoCallState(String state) {
   1106         switch (state.toUpperCase()) {
   1107             case TelephonyConstants.VT_STATE_AUDIO_ONLY:
   1108                 return VIDEO_STATE_AUDIO_ONLY;
   1109             case TelephonyConstants.VT_STATE_TX_ENABLED:
   1110                 return VIDEO_STATE_TX_ENABLED;
   1111             case TelephonyConstants.VT_STATE_RX_ENABLED:
   1112                 return VIDEO_STATE_RX_ENABLED;
   1113             case TelephonyConstants.VT_STATE_BIDIRECTIONAL:
   1114                 return VIDEO_STATE_BIDIRECTIONAL;
   1115             case TelephonyConstants.VT_STATE_TX_PAUSED:
   1116                 return VIDEO_STATE_TX_PAUSED;
   1117             case TelephonyConstants.VT_STATE_RX_PAUSED:
   1118                 return VIDEO_STATE_RX_PAUSED;
   1119             case TelephonyConstants.VT_STATE_BIDIRECTIONAL_PAUSED:
   1120                 return VIDEO_STATE_BIDIRECTIONAL_PAUSED;
   1121 
   1122             default:
   1123         }
   1124         Log.d("getVideoCallState: state is invalid.");
   1125         return CallCallback.STATE_INVALID;
   1126     }
   1127 
   1128     private static int getVideoCallQuality(String quality) {
   1129 
   1130         switch (quality.toUpperCase()) {
   1131             case TelephonyConstants.VT_VIDEO_QUALITY_UNKNOWN:
   1132                 return VideoProfile.QUALITY_UNKNOWN;
   1133             case TelephonyConstants.VT_VIDEO_QUALITY_HIGH:
   1134                 return VideoProfile.QUALITY_HIGH;
   1135             case TelephonyConstants.VT_VIDEO_QUALITY_MEDIUM:
   1136                 return VideoProfile.QUALITY_MEDIUM;
   1137             case TelephonyConstants.VT_VIDEO_QUALITY_LOW:
   1138                 return VideoProfile.QUALITY_LOW;
   1139             case TelephonyConstants.VT_VIDEO_QUALITY_DEFAULT:
   1140                 return VideoProfile.QUALITY_DEFAULT;
   1141             default:
   1142         }
   1143         Log.d("getVideoCallQuality: quality is invalid.");
   1144         return QUALITY_INVALID;
   1145     }
   1146 
   1147     public static String getVideoCallQualityString(int quality) {
   1148         switch (quality) {
   1149             case VideoProfile.QUALITY_UNKNOWN:
   1150                 return TelephonyConstants.VT_VIDEO_QUALITY_UNKNOWN;
   1151             case VideoProfile.QUALITY_HIGH:
   1152                 return TelephonyConstants.VT_VIDEO_QUALITY_HIGH;
   1153             case VideoProfile.QUALITY_MEDIUM:
   1154                 return TelephonyConstants.VT_VIDEO_QUALITY_MEDIUM;
   1155             case VideoProfile.QUALITY_LOW:
   1156                 return TelephonyConstants.VT_VIDEO_QUALITY_LOW;
   1157             case VideoProfile.QUALITY_DEFAULT:
   1158                 return TelephonyConstants.VT_VIDEO_QUALITY_DEFAULT;
   1159             default:
   1160         }
   1161         Log.d("getVideoCallQualityString: quality is invalid.");
   1162         return TelephonyConstants.VT_VIDEO_QUALITY_INVALID;
   1163     }
   1164 
   1165     private static int getCallCallbackEvent(String event) {
   1166 
   1167         switch (event.toUpperCase()) {
   1168             case "EVENT_STATE_CHANGED":
   1169                 return CallCallback.EVENT_STATE_CHANGED;
   1170             case "EVENT_PARENT_CHANGED":
   1171                 return CallCallback.EVENT_PARENT_CHANGED;
   1172             case "EVENT_CHILDREN_CHANGED":
   1173                 return CallCallback.EVENT_CHILDREN_CHANGED;
   1174             case "EVENT_DETAILS_CHANGED":
   1175                 return CallCallback.EVENT_DETAILS_CHANGED;
   1176             case "EVENT_CANNED_TEXT_RESPONSES_LOADED":
   1177                 return CallCallback.EVENT_CANNED_TEXT_RESPONSES_LOADED;
   1178             case "EVENT_POST_DIAL_WAIT":
   1179                 return CallCallback.EVENT_POST_DIAL_WAIT;
   1180             case "EVENT_VIDEO_CALL_CHANGED":
   1181                 return CallCallback.EVENT_VIDEO_CALL_CHANGED;
   1182             case "EVENT_CALL_DESTROYED":
   1183                 return CallCallback.EVENT_CALL_DESTROYED;
   1184             case "EVENT_CONFERENCABLE_CALLS_CHANGED":
   1185                 return CallCallback.EVENT_CONFERENCABLE_CALLS_CHANGED;
   1186         }
   1187         Log.d("getCallCallbackEvent: event is invalid.");
   1188         return CallCallback.EVENT_INVALID;
   1189     }
   1190 
   1191     public static String getCallCallbackEventString(int event) {
   1192 
   1193         switch (event) {
   1194             case CallCallback.EVENT_STATE_CHANGED:
   1195                 return "EVENT_STATE_CHANGED";
   1196             case CallCallback.EVENT_PARENT_CHANGED:
   1197                 return "EVENT_PARENT_CHANGED";
   1198             case CallCallback.EVENT_CHILDREN_CHANGED:
   1199                 return "EVENT_CHILDREN_CHANGED";
   1200             case CallCallback.EVENT_DETAILS_CHANGED:
   1201                 return "EVENT_DETAILS_CHANGED";
   1202             case CallCallback.EVENT_CANNED_TEXT_RESPONSES_LOADED:
   1203                 return "EVENT_CANNED_TEXT_RESPONSES_LOADED";
   1204             case CallCallback.EVENT_POST_DIAL_WAIT:
   1205                 return "EVENT_POST_DIAL_WAIT";
   1206             case CallCallback.EVENT_VIDEO_CALL_CHANGED:
   1207                 return "EVENT_VIDEO_CALL_CHANGED";
   1208             case CallCallback.EVENT_CALL_DESTROYED:
   1209                 return "EVENT_CALL_DESTROYED";
   1210             case CallCallback.EVENT_CONFERENCABLE_CALLS_CHANGED:
   1211                 return "EVENT_CONFERENCABLE_CALLS_CHANGED";
   1212         }
   1213         Log.d("getCallCallbackEventString: event is invalid.");
   1214         return "EVENT_INVALID";
   1215     }
   1216 
   1217     private static int getVideoCallCallbackEvent(String event) {
   1218 
   1219         switch (event) {
   1220             case TelephonyConstants.EVENT_VIDEO_SESSION_MODIFY_REQUEST_RECEIVED:
   1221                 return VideoCallCallback.EVENT_SESSION_MODIFY_REQUEST_RECEIVED;
   1222             case TelephonyConstants.EVENT_VIDEO_SESSION_MODIFY_RESPONSE_RECEIVED:
   1223                 return VideoCallCallback.EVENT_SESSION_MODIFY_RESPONSE_RECEIVED;
   1224             case TelephonyConstants.EVENT_VIDEO_SESSION_EVENT:
   1225                 return VideoCallCallback.EVENT_SESSION_EVENT;
   1226             case TelephonyConstants.EVENT_VIDEO_PEER_DIMENSIONS_CHANGED:
   1227                 return VideoCallCallback.EVENT_PEER_DIMENSIONS_CHANGED;
   1228             case TelephonyConstants.EVENT_VIDEO_QUALITY_CHANGED:
   1229                 return VideoCallCallback.EVENT_VIDEO_QUALITY_CHANGED;
   1230             case TelephonyConstants.EVENT_VIDEO_DATA_USAGE_CHANGED:
   1231                 return VideoCallCallback.EVENT_DATA_USAGE_CHANGED;
   1232             case TelephonyConstants.EVENT_VIDEO_CAMERA_CAPABILITIES_CHANGED:
   1233                 return VideoCallCallback.EVENT_CAMERA_CAPABILITIES_CHANGED;
   1234         }
   1235         Log.d("getVideoCallCallbackEvent: event is invalid.");
   1236         return CallCallback.EVENT_INVALID;
   1237     }
   1238 
   1239     public static String getVideoCallCallbackEventString(int event) {
   1240 
   1241         switch (event) {
   1242             case VideoCallCallback.EVENT_SESSION_MODIFY_REQUEST_RECEIVED:
   1243                 return TelephonyConstants.EVENT_VIDEO_SESSION_MODIFY_REQUEST_RECEIVED;
   1244             case VideoCallCallback.EVENT_SESSION_MODIFY_RESPONSE_RECEIVED:
   1245                 return TelephonyConstants.EVENT_VIDEO_SESSION_MODIFY_RESPONSE_RECEIVED;
   1246             case VideoCallCallback.EVENT_SESSION_EVENT:
   1247                 return TelephonyConstants.EVENT_VIDEO_SESSION_EVENT;
   1248             case VideoCallCallback.EVENT_PEER_DIMENSIONS_CHANGED:
   1249                 return TelephonyConstants.EVENT_VIDEO_PEER_DIMENSIONS_CHANGED;
   1250             case VideoCallCallback.EVENT_VIDEO_QUALITY_CHANGED:
   1251                 return TelephonyConstants.EVENT_VIDEO_QUALITY_CHANGED;
   1252             case VideoCallCallback.EVENT_DATA_USAGE_CHANGED:
   1253                 return TelephonyConstants.EVENT_VIDEO_DATA_USAGE_CHANGED;
   1254             case VideoCallCallback.EVENT_CAMERA_CAPABILITIES_CHANGED:
   1255                 return TelephonyConstants.EVENT_VIDEO_CAMERA_CAPABILITIES_CHANGED;
   1256         }
   1257         Log.d("getVideoCallCallbackEventString: event is invalid.");
   1258         return TelephonyConstants.EVENT_VIDEO_INVALID;
   1259     }
   1260 
   1261     public static String getCallStateString(int state) {
   1262         switch (state) {
   1263             case Call.STATE_NEW:
   1264                 return TelephonyConstants.CALL_STATE_NEW;
   1265             case Call.STATE_DIALING:
   1266                 return TelephonyConstants.CALL_STATE_DIALING;
   1267             case Call.STATE_RINGING:
   1268                 return TelephonyConstants.CALL_STATE_RINGING;
   1269             case Call.STATE_HOLDING:
   1270                 return TelephonyConstants.CALL_STATE_HOLDING;
   1271             case Call.STATE_ACTIVE:
   1272                 return TelephonyConstants.CALL_STATE_ACTIVE;
   1273             case Call.STATE_DISCONNECTED:
   1274                 return TelephonyConstants.CALL_STATE_DISCONNECTED;
   1275             case Call.STATE_PRE_DIAL_WAIT:
   1276                 return TelephonyConstants.CALL_STATE_PRE_DIAL_WAIT;
   1277             case Call.STATE_CONNECTING:
   1278                 return TelephonyConstants.CALL_STATE_CONNECTING;
   1279             case Call.STATE_DISCONNECTING:
   1280                 return TelephonyConstants.CALL_STATE_DISCONNECTING;
   1281             case STATE_INVALID:
   1282                 return TelephonyConstants.CALL_STATE_INVALID;
   1283             default:
   1284                 return TelephonyConstants.CALL_STATE_UNKNOWN;
   1285         }
   1286     }
   1287 
   1288     private static int getAudioRoute(String audioRoute) {
   1289         switch (audioRoute.toUpperCase()) {
   1290             case TelephonyConstants.AUDIO_ROUTE_BLUETOOTH:
   1291                 return CallAudioState.ROUTE_BLUETOOTH;
   1292             case TelephonyConstants.AUDIO_ROUTE_EARPIECE:
   1293                 return CallAudioState.ROUTE_EARPIECE;
   1294             case TelephonyConstants.AUDIO_ROUTE_SPEAKER:
   1295                 return CallAudioState.ROUTE_SPEAKER;
   1296             case TelephonyConstants.AUDIO_ROUTE_WIRED_HEADSET:
   1297                 return CallAudioState.ROUTE_WIRED_HEADSET;
   1298             case TelephonyConstants.AUDIO_ROUTE_WIRED_OR_EARPIECE:
   1299                 return CallAudioState.ROUTE_WIRED_OR_EARPIECE;
   1300             default:
   1301                 return INVALID_AUDIO_ROUTE;
   1302         }
   1303     }
   1304 
   1305     public static String getAudioRouteString(int audioRoute) {
   1306         return CallAudioState.audioRouteToString(audioRoute);
   1307     }
   1308 
   1309     public static String getVideoCallSessionEventString(int event) {
   1310 
   1311         switch (event) {
   1312             case Connection.VideoProvider.SESSION_EVENT_RX_PAUSE:
   1313                 return TelephonyConstants.SESSION_EVENT_RX_PAUSE;
   1314             case Connection.VideoProvider.SESSION_EVENT_RX_RESUME:
   1315                 return TelephonyConstants.SESSION_EVENT_RX_RESUME;
   1316             case Connection.VideoProvider.SESSION_EVENT_TX_START:
   1317                 return TelephonyConstants.SESSION_EVENT_TX_START;
   1318             case Connection.VideoProvider.SESSION_EVENT_TX_STOP:
   1319                 return TelephonyConstants.SESSION_EVENT_TX_STOP;
   1320             case Connection.VideoProvider.SESSION_EVENT_CAMERA_FAILURE:
   1321                 return TelephonyConstants.SESSION_EVENT_CAMERA_FAILURE;
   1322             case Connection.VideoProvider.SESSION_EVENT_CAMERA_READY:
   1323                 return TelephonyConstants.SESSION_EVENT_CAMERA_READY;
   1324             default:
   1325                 return TelephonyConstants.SESSION_EVENT_UNKNOWN;
   1326         }
   1327     }
   1328 
   1329     public static String getCallCapabilityString(int capability) {
   1330         switch (capability) {
   1331             case Call.Details.CAPABILITY_HOLD:
   1332                 return TelephonyConstants.CALL_CAPABILITY_HOLD;
   1333             case Call.Details.CAPABILITY_SUPPORT_HOLD:
   1334                 return TelephonyConstants.CALL_CAPABILITY_SUPPORT_HOLD;
   1335             case Call.Details.CAPABILITY_MERGE_CONFERENCE:
   1336                 return TelephonyConstants.CALL_CAPABILITY_MERGE_CONFERENCE;
   1337             case Call.Details.CAPABILITY_SWAP_CONFERENCE:
   1338                 return TelephonyConstants.CALL_CAPABILITY_SWAP_CONFERENCE;
   1339             case Call.Details.CAPABILITY_UNUSED_1:
   1340                 return TelephonyConstants.CALL_CAPABILITY_UNUSED_1;
   1341             case Call.Details.CAPABILITY_RESPOND_VIA_TEXT:
   1342                 return TelephonyConstants.CALL_CAPABILITY_RESPOND_VIA_TEXT;
   1343             case Call.Details.CAPABILITY_MUTE:
   1344                 return TelephonyConstants.CALL_CAPABILITY_MUTE;
   1345             case Call.Details.CAPABILITY_MANAGE_CONFERENCE:
   1346                 return TelephonyConstants.CALL_CAPABILITY_MANAGE_CONFERENCE;
   1347             case Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_RX:
   1348                 return TelephonyConstants.CALL_CAPABILITY_SUPPORTS_VT_LOCAL_RX;
   1349             case Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_TX:
   1350                 return TelephonyConstants.CALL_CAPABILITY_SUPPORTS_VT_LOCAL_TX;
   1351             case Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL:
   1352                 return TelephonyConstants.CALL_CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL;
   1353             case Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_RX:
   1354                 return TelephonyConstants.CALL_CAPABILITY_SUPPORTS_VT_REMOTE_RX;
   1355             case Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_TX:
   1356                 return TelephonyConstants.CALL_CAPABILITY_SUPPORTS_VT_REMOTE_TX;
   1357             case Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL:
   1358                 return TelephonyConstants.CALL_CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL;
   1359             case Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE:
   1360                 return TelephonyConstants.CALL_CAPABILITY_SEPARATE_FROM_CONFERENCE;
   1361             case Call.Details.CAPABILITY_DISCONNECT_FROM_CONFERENCE:
   1362                 return TelephonyConstants.CALL_CAPABILITY_DISCONNECT_FROM_CONFERENCE;
   1363             case Call.Details.CAPABILITY_SPEED_UP_MT_AUDIO:
   1364                 return TelephonyConstants.CALL_CAPABILITY_SPEED_UP_MT_AUDIO;
   1365             case Call.Details.CAPABILITY_CAN_UPGRADE_TO_VIDEO:
   1366                 return TelephonyConstants.CALL_CAPABILITY_CAN_UPGRADE_TO_VIDEO;
   1367             case Call.Details.CAPABILITY_CAN_PAUSE_VIDEO:
   1368                 return TelephonyConstants.CALL_CAPABILITY_CAN_PAUSE_VIDEO;
   1369         }
   1370         return TelephonyConstants.CALL_CAPABILITY_UNKOWN;
   1371     }
   1372 
   1373     public static List<String> getCallCapabilitiesString(int capabilities) {
   1374         final int[] capabilityConstants = new int[] {
   1375                 Call.Details.CAPABILITY_HOLD,
   1376                 Call.Details.CAPABILITY_SUPPORT_HOLD,
   1377                 Call.Details.CAPABILITY_MERGE_CONFERENCE,
   1378                 Call.Details.CAPABILITY_SWAP_CONFERENCE,
   1379                 Call.Details.CAPABILITY_UNUSED_1,
   1380                 Call.Details.CAPABILITY_RESPOND_VIA_TEXT,
   1381                 Call.Details.CAPABILITY_MUTE,
   1382                 Call.Details.CAPABILITY_MANAGE_CONFERENCE,
   1383                 Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_RX,
   1384                 Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_TX,
   1385                 Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL,
   1386                 Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_RX,
   1387                 Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_TX,
   1388                 Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL,
   1389                 Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE,
   1390                 Call.Details.CAPABILITY_DISCONNECT_FROM_CONFERENCE,
   1391                 Call.Details.CAPABILITY_SPEED_UP_MT_AUDIO,
   1392                 Call.Details.CAPABILITY_CAN_UPGRADE_TO_VIDEO,
   1393                 Call.Details.CAPABILITY_CAN_PAUSE_VIDEO
   1394         };
   1395 
   1396         List<String> capabilityList = new ArrayList<String>();
   1397 
   1398         for (int capability : capabilityConstants) {
   1399             if ((capabilities & capability) == capability) {
   1400                 capabilityList.add(getCallCapabilityString(capability));
   1401             }
   1402         }
   1403         return capabilityList;
   1404     }
   1405 
   1406     public static String getCallPropertyString(int property) {
   1407 
   1408         switch (property) {
   1409             case Call.Details.PROPERTY_CONFERENCE:
   1410                 return TelephonyConstants.CALL_PROPERTY_CONFERENCE;
   1411             case Call.Details.PROPERTY_GENERIC_CONFERENCE:
   1412                 return TelephonyConstants.CALL_PROPERTY_GENERIC_CONFERENCE;
   1413             case Call.Details.PROPERTY_EMERGENCY_CALLBACK_MODE:
   1414                 return TelephonyConstants.CALL_PROPERTY_EMERGENCY_CALLBACK_MODE;
   1415             case Call.Details.PROPERTY_WIFI:
   1416                 return TelephonyConstants.CALL_PROPERTY_WIFI;
   1417             case Call.Details.PROPERTY_HIGH_DEF_AUDIO:
   1418                 return TelephonyConstants.CALL_PROPERTY_HIGH_DEF_AUDIO;
   1419             default:
   1420                 return TelephonyConstants.CALL_PROPERTY_UNKNOWN;
   1421         }
   1422     }
   1423 
   1424     public static List<String> getCallPropertiesString(int properties) {
   1425         final int[] propertyConstants = new int[] {
   1426                 Call.Details.PROPERTY_CONFERENCE,
   1427                 Call.Details.PROPERTY_GENERIC_CONFERENCE,
   1428                 Call.Details.PROPERTY_EMERGENCY_CALLBACK_MODE,
   1429                 Call.Details.PROPERTY_WIFI,
   1430                 Call.Details.PROPERTY_HIGH_DEF_AUDIO
   1431         };
   1432 
   1433         List<String> propertyList = new ArrayList<String>();
   1434 
   1435         for (int property : propertyConstants) {
   1436             if ((properties & property) == property) {
   1437                 propertyList.add(getCallPropertyString(property));
   1438             }
   1439         }
   1440 
   1441         return propertyList;
   1442     }
   1443 
   1444     public static String getCallPresentationInfoString(int presentation) {
   1445         switch (presentation) {
   1446             case TelecomManager.PRESENTATION_ALLOWED:
   1447                 return TelephonyConstants.CALL_PRESENTATION_ALLOWED;
   1448             case TelecomManager.PRESENTATION_RESTRICTED:
   1449                 return TelephonyConstants.CALL_PRESENTATION_RESTRICTED;
   1450             case TelecomManager.PRESENTATION_PAYPHONE:
   1451                 return TelephonyConstants.CALL_PRESENTATION_PAYPHONE;
   1452             default:
   1453                 return TelephonyConstants.CALL_PRESENTATION_UNKNOWN;
   1454         }
   1455     }
   1456 }
   1457