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