• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
getService()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 
startListeningForEvent( int event )54         public static void startListeningForEvent( int event ) {
55             sListenedEvents |= event & LISTEN_ALL;
56         }
57 
stopListeningForEvent( int event )58         public static void stopListeningForEvent( int event ) {
59             sListenedEvents &= ~(event & LISTEN_ALL);
60         }
61 
onCallAdded(String callId, Call call)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 
onCallRemoved(String callId, Call call)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 
CallEvent(String callId, EventType event)116         CallEvent(String callId, EventType event) {
117             mCallId = callId;
118             mEvent = event;
119         }
120 
getCallId()121         public String getCallId() {
122             return mCallId;
123         }
124 
getEvent()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> {
VideoCallEvent(String callId, EventType event)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 
CallCallback(String callId, int events)168         public CallCallback(String callId, int events) {
169             super();
170             mEvents = events & EVENT_ALL;
171             mCallId = callId;
172         }
173 
startListeningForEvents(int events)174         public void startListeningForEvents(int events) {
175             mEvents |= events & EVENT_ALL;
176         }
177 
stopListeningForEvents(int events)178         public void stopListeningForEvents(int events) {
179             mEvents &= ~(events & EVENT_ALL);
180         }
181 
182         @Override
onStateChanged( Call call, int state)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
onParentChanged( Call call, Call parent)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
onChildrenChanged( Call call, List<Call> children)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
onDetailsChanged( Call call, Details details)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
onCannedTextResponsesLoaded( Call call, List<String> cannedTextResponses)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
onPostDialWait( Call call, String remainingPostDialSequence)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
onVideoCallChanged( Call call, InCallService.VideoCall videoCall)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
onCallDestroyed(Call call)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
onConferenceableCallsChanged( Call call, List<Call> conferenceableCalls)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 
VideoCallCallback(String callId, int listeners)376         public VideoCallCallback(String callId, int listeners) {
377 
378             mCallId = callId;
379             mEvents = listeners & EVENT_ALL;
380         }
381 
startListeningForEvents(int events)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 
stopListeningForEvents(int events)391         public void stopListeningForEvents(int events) {
392             mEvents &= ~(events & EVENT_ALL);
393         }
394 
395         @Override
onSessionModifyRequestReceived(VideoProfile videoProfile)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
onSessionModifyResponseReceived(int status, VideoProfile requestedProfile, VideoProfile responseProfile)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
onCallSessionEvent(int event)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
onPeerDimensionsChanged(int width, int height)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
onVideoQualityChanged(int videoQuality)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
onCallDataUsageChanged(long dataUsage)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
onCameraCapabilitiesChanged( CameraCapabilities cameraCapabilities)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 
CallContainer(Call call, CallCallback callback, VideoCall videoCall, VideoCallCallback videoCallCallback)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 
getCall()519         public Call getCall() {
520             return mCall;
521         }
522 
getCallback()523         public CallCallback getCallback() {
524             return mCallCallback;
525         }
526 
getVideoCall()527         public InCallService.VideoCall getVideoCall() {
528             return mVideoCall;
529         }
530 
getVideoCallCallback()531         public VideoCallCallback getVideoCallCallback() {
532             return mVideoCallCallback;
533         }
534 
updateVideoCall(VideoCall videoCall, VideoCallCallback videoCallCallback)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
onCallAdded(Call call)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
onCallRemoved(Call call)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 
setEventFacade(EventFacade facade)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 
servicePostEvent(String eventName, Object event)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 
getCallId(Call call)634     public static String getCallId(Call call) {
635         if (call != null) {
636             return "Call:" + call.hashCode();
637         }
638         else
639             return "";
640     }
641 
getVideoCallId(InCallServiceImpl.VideoCall videoCall)642     public static String getVideoCallId(InCallServiceImpl.VideoCall videoCall) {
643         if (videoCall != null)
644             return "VideoCall:" + videoCall.hashCode();
645         else
646             return "";
647     }
648 
getCallById(String callId)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 
getCallCallbackById(String callId)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 
getVideoCallById(String callId)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
getVideoCallListenerById(String callId)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 
callDisconnect(String callId)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 
holdCall(String callId)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 
muteCall(Boolean shouldMute)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 
mergeCallsInConference(String callId)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 
splitCallFromConf(String callId)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 
unholdCall(String callId)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 
joinCallsInConf(String callIdOne, String callIdTwo)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 
getCallIdList()768     public static Set<String> getCallIdList() {
769         return mCallContainerMap.keySet();
770     }
771 
clearCallList()772     public static void clearCallList() {
773         mCallContainerMap.clear();
774     }
775 
callGetState(String callId)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 
callGetDetails(String callId)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 
callGetCallProperties(String callId)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 
callGetCallCapabilities(String callId)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")
overrideProximitySensor(Boolean screenOn)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 
serviceGetCallAudioState()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
serviceSetAudioRoute(String route)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 
callStartListeningForEvent(String callId, String strEvent)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 
callStopListeningForEvent(String callId, String strEvent)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 
videoCallStartListeningForEvent(String callId, String strEvent)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 
videoCallStopListeningForEvent(String callId, String strEvent)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 
videoCallGetState(String callId)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 
videoCallSendSessionModifyRequest( String callId, String videoStateString, String videoQualityString)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 
videoCallSendSessionModifyResponse( String callId, String videoStateString, String videoQualityString)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 
callAnswer(String callId, String videoState)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 
callReject(String callId, String message)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 
getCallParent(String callId)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 
getCallChildren(String callId)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 
swapCallsInConference(String callId)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 
callPlayDtmfTone(String callId, char digit)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 
callStopDtmfTone(String callId)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 
callGetCannedTextResponses(String callId)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 
getVideoCallStateString(int state)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 
getVideoCallState(String state)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 
getVideoCallQuality(String quality)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 
getVideoCallQualityString(int quality)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 
getCallCallbackEvent(String event)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 
getCallCallbackEventString(int event)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 
getVideoCallCallbackEvent(String event)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 
getVideoCallCallbackEventString(int event)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 
getCallStateString(int state)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 
getAudioRoute(String audioRoute)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 
getAudioRouteString(int audioRoute)1314     public static String getAudioRouteString(int audioRoute) {
1315         return CallAudioState.audioRouteToString(audioRoute);
1316     }
1317 
getVideoCallSessionEventString(int event)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 
getCallCapabilityString(int capability)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 
getCallCapabilitiesString(int capabilities)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 
getCallPropertyString(int property)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 
getCallPropertiesString(int properties)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 
getCallPresentationInfoString(int presentation)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