• 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 
mergeCallsInConference(String callId)718     public static void mergeCallsInConference(String callId) {
719         Call c = getCallById(callId);
720         if (c == null) {
721             Log.d("mergeCallsInConference: callId is null");
722             return;
723         }
724         c.mergeConference();
725     }
726 
splitCallFromConf(String callId)727     public static void splitCallFromConf(String callId) {
728         Call c = getCallById(callId);
729         if (c == null) {
730             Log.d("splitCallFromConf: callId is null");
731             return;
732         }
733         c.splitFromConference();
734     }
735 
unholdCall(String callId)736     public static void unholdCall(String callId) {
737         Call c = getCallById(callId);
738         if (c == null) {
739             Log.d("unholdCall: callId is null");
740             return;
741         }
742         c.unhold();
743     }
744 
joinCallsInConf(String callIdOne, String callIdTwo)745     public static void joinCallsInConf(String callIdOne, String callIdTwo) {
746         Call callOne = getCallById(callIdOne);
747         Call callTwo = getCallById(callIdTwo);
748 
749         if (callOne == null || callTwo == null) {
750             Log.d("joinCallsInConf: callOne or CallTwo is null");
751             return;
752         }
753 
754         callOne.conference(callTwo);
755     }
756 
getCallIdList()757     public static Set<String> getCallIdList() {
758         return mCallContainerMap.keySet();
759     }
760 
clearCallList()761     public static void clearCallList() {
762         mCallContainerMap.clear();
763     }
764 
callGetState(String callId)765     public static String callGetState(String callId) {
766         Call c = getCallById(callId);
767         if (c == null) {
768             return getCallStateString(STATE_INVALID);
769         }
770 
771         return getCallStateString(c.getState());
772     }
773 
callGetDetails(String callId)774     public static Call.Details callGetDetails(String callId) {
775         Call c = getCallById(callId);
776         if (c == null) {
777             Log.d(String.format("Couldn't find an active call with ID:%s", callId));
778             return null;
779         }
780 
781         return c.getDetails();
782     }
783 
callGetCallProperties(String callId)784     public static List<String> callGetCallProperties(String callId) {
785         Call.Details details = callGetDetails(callId);
786 
787         if (details == null) {
788             return null;
789         }
790 
791         return getCallPropertiesString(details.getCallProperties());
792     }
793 
callGetCallCapabilities(String callId)794     public static List<String> callGetCallCapabilities(String callId) {
795         Call.Details details = callGetDetails(callId);
796 
797         if (details == null) {
798             return null;
799         }
800 
801         return getCallCapabilitiesString(details.getCallCapabilities());
802     }
803 
804     @SuppressWarnings("deprecation")
overrideProximitySensor(Boolean screenOn)805     public static void overrideProximitySensor(Boolean screenOn) {
806         InCallServiceImpl svc = getService();
807         if (svc == null) {
808             Log.d("overrideProximitySensor: InCallServiceImpl is null.");
809             return;
810         }
811 
812         Phone phone = svc.getPhone();
813         if (phone == null) {
814             Log.d("overrideProximitySensor: phone is null.");
815             return;
816         }
817 
818         phone.setProximitySensorOff(screenOn);
819     }
820 
serviceGetCallAudioState()821     public static CallAudioState serviceGetCallAudioState() {
822         InCallServiceImpl svc = getService();
823 
824         if (svc != null) {
825             return svc.getCallAudioState();
826         }
827         else {
828             return null;
829         }
830     }
831 
832     // Wonky name due to conflict with internal function
serviceSetAudioRoute(String route)833     public static void serviceSetAudioRoute(String route) {
834         InCallServiceImpl svc = getService();
835 
836         if (svc == null) {
837             Log.d("serviceSetAudioRoute: InCallServiceImpl is null.");
838             return;
839         }
840 
841         int r = getAudioRoute(route);
842 
843         Log.d(String.format("Setting Audio Route to %s:%d", route, r));
844 
845         if (r == INVALID_AUDIO_ROUTE) {
846             Log.d(String.format("Invalid Audio route %s:%d", route, r));
847             return;
848         }
849         svc.setAudioRoute(r);
850     }
851 
callStartListeningForEvent(String callId, String strEvent)852     public static void callStartListeningForEvent(String callId, String strEvent) {
853 
854         CallCallback cl = getCallCallbackById(callId);
855 
856         if (cl == null) {
857             Log.d("callStartListeningForEvent: CallCallback is null.");
858             return;
859         }
860 
861         int event = getCallCallbackEvent(strEvent);
862 
863         if (event == CallCallback.EVENT_INVALID) {
864             Log.d("callStartListeningForEvent: event is invalid.");
865             return;
866         }
867 
868         cl.startListeningForEvents(event);
869     }
870 
callStopListeningForEvent(String callId, String strEvent)871     public static void callStopListeningForEvent(String callId, String strEvent) {
872         CallCallback cl = getCallCallbackById(callId);
873 
874         if (cl == null) {
875             Log.d("callStopListeningForEvent: CallCallback is null.");
876             return;
877         }
878 
879         int event = getCallCallbackEvent(strEvent);
880 
881         if (event == CallCallback.EVENT_INVALID) {
882             Log.d("callStopListeningForEvent: event is invalid.");
883             return;
884         }
885 
886         cl.stopListeningForEvents(event);
887     }
888 
videoCallStartListeningForEvent(String callId, String strEvent)889     public static void videoCallStartListeningForEvent(String callId, String strEvent) {
890         VideoCallCallback cl = getVideoCallListenerById(callId);
891 
892         if (cl == null) {
893             Log.d(String.format("Couldn't find a call with call id:%s", callId));
894             return;
895         }
896 
897         int event = getVideoCallCallbackEvent(strEvent);
898 
899         if (event == VideoCallCallback.EVENT_INVALID) {
900             Log.d(String.format("Failed to find a valid event:[%s]", strEvent));
901             return;
902         }
903 
904         cl.startListeningForEvents(event);
905     }
906 
videoCallStopListeningForEvent(String callId, String strEvent)907     public static void videoCallStopListeningForEvent(String callId, String strEvent) {
908         VideoCallCallback cl = getVideoCallListenerById(callId);
909 
910         if (cl == null) {
911             Log.d("videoCallStopListeningForEvent: CallCallback is null.");
912             return;
913         }
914 
915         int event = getVideoCallCallbackEvent(strEvent);
916 
917         if (event == VideoCallCallback.EVENT_INVALID) {
918             Log.d("getVideoCallCallbackEvent: event is invalid.");
919             return;
920         }
921 
922         cl.stopListeningForEvents(event);
923     }
924 
videoCallGetState(String callId)925     public static String videoCallGetState(String callId) {
926         Call c = getCallById(callId);
927 
928         int state = CallCallback.STATE_INVALID;
929 
930         if (c == null) {
931             Log.d("videoCallGetState: call is null.");
932         }
933         else {
934             state = c.getDetails().getVideoState();
935         }
936 
937         return getVideoCallStateString(state);
938     }
939 
videoCallSendSessionModifyRequest( String callId, String videoStateString, String videoQualityString)940     public static void videoCallSendSessionModifyRequest(
941             String callId, String videoStateString, String videoQualityString) {
942         VideoCall vc = getVideoCallById(callId);
943 
944         if (vc == null) {
945             Log.d("Invalid video call for call ID");
946             return;
947         }
948 
949         int videoState = getVideoCallState(videoStateString);
950         int videoQuality = getVideoCallQuality(videoQualityString);
951 
952         Log.d(String.format("Sending Modify request for %s:%d, %s:%d",
953                 videoStateString, videoState, videoQualityString, videoQuality));
954 
955         if (videoState == CallCallback.STATE_INVALID ||
956                 videoQuality == QUALITY_INVALID || videoQuality == VideoProfile.QUALITY_UNKNOWN) {
957             Log.d("Invalid session modify request!");
958             return;
959         }
960 
961         vc.sendSessionModifyRequest(new VideoProfile(videoState, videoQuality));
962     }
963 
videoCallSendSessionModifyResponse( String callId, String videoStateString, String videoQualityString)964     public static void videoCallSendSessionModifyResponse(
965             String callId, String videoStateString, String videoQualityString) {
966         VideoCall vc = getVideoCallById(callId);
967 
968         if (vc == null) {
969             Log.d("Invalid video call for call ID");
970             return;
971         }
972 
973         int videoState = getVideoCallState(videoStateString);
974         int videoQuality = getVideoCallQuality(videoQualityString);
975 
976         Log.d(String.format("Sending Modify request for %s:%d, %s:%d",
977                 videoStateString, videoState, videoQualityString, videoQuality));
978 
979         if (videoState == CallCallback.STATE_INVALID ||
980                 videoQuality == QUALITY_INVALID || videoQuality == VideoProfile.QUALITY_UNKNOWN) {
981             Log.d("Invalid session modify request!");
982             return;
983         }
984 
985         vc.sendSessionModifyResponse(new VideoProfile(videoState, videoQuality));
986     }
987 
callAnswer(String callId, String videoState)988     public static void callAnswer(String callId, String videoState) {
989         Call c = getCallById(callId);
990 
991         if (c == null) {
992             Log.d("callAnswer: call is null.");
993         }
994 
995         int state = getVideoCallState(videoState);
996 
997         if (state == CallCallback.STATE_INVALID) {
998             Log.d("callAnswer: video state is invalid.");
999             state = VideoProfile.STATE_AUDIO_ONLY;
1000         }
1001 
1002         c.answer(state);
1003     }
1004 
callReject(String callId, String message)1005     public static void callReject(String callId, String message) {
1006         Call c = getCallById(callId);
1007 
1008         if (c == null) {
1009             Log.d("callReject: call is null.");
1010         }
1011 
1012         c.reject((message != null) ? true : false, message);
1013     }
1014 
getCallParent(String callId)1015     public static String getCallParent(String callId) {
1016         Call c = getCallById(callId);
1017 
1018         if (c == null) {
1019             Log.d("getCallParent: call is null.");
1020             return null;
1021         }
1022         Call callParent = c.getParent();
1023         return getCallId(callParent);
1024     }
1025 
getCallChildren(String callId)1026     public static List<String> getCallChildren(String callId) {
1027         Call c = getCallById(callId);
1028 
1029         if (c == null) {
1030             Log.d("getCallChildren: call is null.");
1031             return null;
1032         }
1033         List<String> childrenList = new ArrayList<String>();
1034         List<Call> callChildren = c.getChildren();
1035         for (Call call : callChildren) {
1036             childrenList.add(getCallId(call));
1037         }
1038         return childrenList;
1039     }
1040 
swapCallsInConference(String callId)1041     public static void swapCallsInConference(String callId) {
1042         Call c = getCallById(callId);
1043         if (c == null) {
1044             Log.d("swapCallsInConference: call is null.");
1045             return;
1046         }
1047         c.swapConference();
1048     }
1049 
callPlayDtmfTone(String callId, char digit)1050     public static void callPlayDtmfTone(String callId, char digit) {
1051         Call c = getCallById(callId);
1052         if (c == null) {
1053             Log.d("callPlayDtmfTone: call is null.");
1054             return;
1055         }
1056         c.playDtmfTone(digit);
1057     }
1058 
callStopDtmfTone(String callId)1059     public static void callStopDtmfTone(String callId) {
1060         Call c = getCallById(callId);
1061         if (c == null) {
1062             Log.d("callStopDtmfTone: call is null.");
1063             return;
1064         }
1065         c.stopDtmfTone();
1066     }
1067 
callGetCannedTextResponses(String callId)1068     public static List<String> callGetCannedTextResponses(String callId) {
1069         Call c = getCallById(callId);
1070         if (c == null) {
1071             return null;
1072         }
1073 
1074         return c.getCannedTextResponses();
1075     }
1076 
1077     /*
1078      * String Mapping Functions for Facade Parameter Translation
1079      */
1080 
getVideoCallStateString(int state)1081     public static String getVideoCallStateString(int state) {
1082         switch (state) {
1083             case VIDEO_STATE_AUDIO_ONLY:
1084                 return TelephonyConstants.VT_STATE_AUDIO_ONLY;
1085             case VIDEO_STATE_TX_ENABLED:
1086                 return TelephonyConstants.VT_STATE_TX_ENABLED;
1087             case VIDEO_STATE_RX_ENABLED:
1088                 return TelephonyConstants.VT_STATE_RX_ENABLED;
1089             case VIDEO_STATE_BIDIRECTIONAL:
1090                 return TelephonyConstants.VT_STATE_BIDIRECTIONAL;
1091             case VIDEO_STATE_TX_PAUSED:
1092                 return TelephonyConstants.VT_STATE_TX_PAUSED;
1093             case VIDEO_STATE_RX_PAUSED:
1094                 return TelephonyConstants.VT_STATE_RX_PAUSED;
1095             case VIDEO_STATE_BIDIRECTIONAL_PAUSED:
1096                 return TelephonyConstants.VT_STATE_BIDIRECTIONAL_PAUSED;
1097             default:
1098         }
1099         Log.d("getVideoCallStateString: state is invalid.");
1100         return TelephonyConstants.VT_STATE_STATE_INVALID;
1101     }
1102 
getVideoCallState(String state)1103     public static int getVideoCallState(String state) {
1104         switch (state.toUpperCase()) {
1105             case TelephonyConstants.VT_STATE_AUDIO_ONLY:
1106                 return VIDEO_STATE_AUDIO_ONLY;
1107             case TelephonyConstants.VT_STATE_TX_ENABLED:
1108                 return VIDEO_STATE_TX_ENABLED;
1109             case TelephonyConstants.VT_STATE_RX_ENABLED:
1110                 return VIDEO_STATE_RX_ENABLED;
1111             case TelephonyConstants.VT_STATE_BIDIRECTIONAL:
1112                 return VIDEO_STATE_BIDIRECTIONAL;
1113             case TelephonyConstants.VT_STATE_TX_PAUSED:
1114                 return VIDEO_STATE_TX_PAUSED;
1115             case TelephonyConstants.VT_STATE_RX_PAUSED:
1116                 return VIDEO_STATE_RX_PAUSED;
1117             case TelephonyConstants.VT_STATE_BIDIRECTIONAL_PAUSED:
1118                 return VIDEO_STATE_BIDIRECTIONAL_PAUSED;
1119 
1120             default:
1121         }
1122         Log.d("getVideoCallState: state is invalid.");
1123         return CallCallback.STATE_INVALID;
1124     }
1125 
getVideoCallQuality(String quality)1126     private static int getVideoCallQuality(String quality) {
1127 
1128         switch (quality.toUpperCase()) {
1129             case TelephonyConstants.VT_VIDEO_QUALITY_UNKNOWN:
1130                 return VideoProfile.QUALITY_UNKNOWN;
1131             case TelephonyConstants.VT_VIDEO_QUALITY_HIGH:
1132                 return VideoProfile.QUALITY_HIGH;
1133             case TelephonyConstants.VT_VIDEO_QUALITY_MEDIUM:
1134                 return VideoProfile.QUALITY_MEDIUM;
1135             case TelephonyConstants.VT_VIDEO_QUALITY_LOW:
1136                 return VideoProfile.QUALITY_LOW;
1137             case TelephonyConstants.VT_VIDEO_QUALITY_DEFAULT:
1138                 return VideoProfile.QUALITY_DEFAULT;
1139             default:
1140         }
1141         Log.d("getVideoCallQuality: quality is invalid.");
1142         return QUALITY_INVALID;
1143     }
1144 
getVideoCallQualityString(int quality)1145     public static String getVideoCallQualityString(int quality) {
1146         switch (quality) {
1147             case VideoProfile.QUALITY_UNKNOWN:
1148                 return TelephonyConstants.VT_VIDEO_QUALITY_UNKNOWN;
1149             case VideoProfile.QUALITY_HIGH:
1150                 return TelephonyConstants.VT_VIDEO_QUALITY_HIGH;
1151             case VideoProfile.QUALITY_MEDIUM:
1152                 return TelephonyConstants.VT_VIDEO_QUALITY_MEDIUM;
1153             case VideoProfile.QUALITY_LOW:
1154                 return TelephonyConstants.VT_VIDEO_QUALITY_LOW;
1155             case VideoProfile.QUALITY_DEFAULT:
1156                 return TelephonyConstants.VT_VIDEO_QUALITY_DEFAULT;
1157             default:
1158         }
1159         Log.d("getVideoCallQualityString: quality is invalid.");
1160         return TelephonyConstants.VT_VIDEO_QUALITY_INVALID;
1161     }
1162 
getCallCallbackEvent(String event)1163     private static int getCallCallbackEvent(String event) {
1164 
1165         switch (event.toUpperCase()) {
1166             case "EVENT_STATE_CHANGED":
1167                 return CallCallback.EVENT_STATE_CHANGED;
1168             case "EVENT_PARENT_CHANGED":
1169                 return CallCallback.EVENT_PARENT_CHANGED;
1170             case "EVENT_CHILDREN_CHANGED":
1171                 return CallCallback.EVENT_CHILDREN_CHANGED;
1172             case "EVENT_DETAILS_CHANGED":
1173                 return CallCallback.EVENT_DETAILS_CHANGED;
1174             case "EVENT_CANNED_TEXT_RESPONSES_LOADED":
1175                 return CallCallback.EVENT_CANNED_TEXT_RESPONSES_LOADED;
1176             case "EVENT_POST_DIAL_WAIT":
1177                 return CallCallback.EVENT_POST_DIAL_WAIT;
1178             case "EVENT_VIDEO_CALL_CHANGED":
1179                 return CallCallback.EVENT_VIDEO_CALL_CHANGED;
1180             case "EVENT_CALL_DESTROYED":
1181                 return CallCallback.EVENT_CALL_DESTROYED;
1182             case "EVENT_CONFERENCABLE_CALLS_CHANGED":
1183                 return CallCallback.EVENT_CONFERENCABLE_CALLS_CHANGED;
1184         }
1185         Log.d("getCallCallbackEvent: event is invalid.");
1186         return CallCallback.EVENT_INVALID;
1187     }
1188 
getCallCallbackEventString(int event)1189     public static String getCallCallbackEventString(int event) {
1190 
1191         switch (event) {
1192             case CallCallback.EVENT_STATE_CHANGED:
1193                 return "EVENT_STATE_CHANGED";
1194             case CallCallback.EVENT_PARENT_CHANGED:
1195                 return "EVENT_PARENT_CHANGED";
1196             case CallCallback.EVENT_CHILDREN_CHANGED:
1197                 return "EVENT_CHILDREN_CHANGED";
1198             case CallCallback.EVENT_DETAILS_CHANGED:
1199                 return "EVENT_DETAILS_CHANGED";
1200             case CallCallback.EVENT_CANNED_TEXT_RESPONSES_LOADED:
1201                 return "EVENT_CANNED_TEXT_RESPONSES_LOADED";
1202             case CallCallback.EVENT_POST_DIAL_WAIT:
1203                 return "EVENT_POST_DIAL_WAIT";
1204             case CallCallback.EVENT_VIDEO_CALL_CHANGED:
1205                 return "EVENT_VIDEO_CALL_CHANGED";
1206             case CallCallback.EVENT_CALL_DESTROYED:
1207                 return "EVENT_CALL_DESTROYED";
1208             case CallCallback.EVENT_CONFERENCABLE_CALLS_CHANGED:
1209                 return "EVENT_CONFERENCABLE_CALLS_CHANGED";
1210         }
1211         Log.d("getCallCallbackEventString: event is invalid.");
1212         return "EVENT_INVALID";
1213     }
1214 
getVideoCallCallbackEvent(String event)1215     private static int getVideoCallCallbackEvent(String event) {
1216 
1217         switch (event) {
1218             case TelephonyConstants.EVENT_VIDEO_SESSION_MODIFY_REQUEST_RECEIVED:
1219                 return VideoCallCallback.EVENT_SESSION_MODIFY_REQUEST_RECEIVED;
1220             case TelephonyConstants.EVENT_VIDEO_SESSION_MODIFY_RESPONSE_RECEIVED:
1221                 return VideoCallCallback.EVENT_SESSION_MODIFY_RESPONSE_RECEIVED;
1222             case TelephonyConstants.EVENT_VIDEO_SESSION_EVENT:
1223                 return VideoCallCallback.EVENT_SESSION_EVENT;
1224             case TelephonyConstants.EVENT_VIDEO_PEER_DIMENSIONS_CHANGED:
1225                 return VideoCallCallback.EVENT_PEER_DIMENSIONS_CHANGED;
1226             case TelephonyConstants.EVENT_VIDEO_QUALITY_CHANGED:
1227                 return VideoCallCallback.EVENT_VIDEO_QUALITY_CHANGED;
1228             case TelephonyConstants.EVENT_VIDEO_DATA_USAGE_CHANGED:
1229                 return VideoCallCallback.EVENT_DATA_USAGE_CHANGED;
1230             case TelephonyConstants.EVENT_VIDEO_CAMERA_CAPABILITIES_CHANGED:
1231                 return VideoCallCallback.EVENT_CAMERA_CAPABILITIES_CHANGED;
1232         }
1233         Log.d("getVideoCallCallbackEvent: event is invalid.");
1234         return CallCallback.EVENT_INVALID;
1235     }
1236 
getVideoCallCallbackEventString(int event)1237     public static String getVideoCallCallbackEventString(int event) {
1238 
1239         switch (event) {
1240             case VideoCallCallback.EVENT_SESSION_MODIFY_REQUEST_RECEIVED:
1241                 return TelephonyConstants.EVENT_VIDEO_SESSION_MODIFY_REQUEST_RECEIVED;
1242             case VideoCallCallback.EVENT_SESSION_MODIFY_RESPONSE_RECEIVED:
1243                 return TelephonyConstants.EVENT_VIDEO_SESSION_MODIFY_RESPONSE_RECEIVED;
1244             case VideoCallCallback.EVENT_SESSION_EVENT:
1245                 return TelephonyConstants.EVENT_VIDEO_SESSION_EVENT;
1246             case VideoCallCallback.EVENT_PEER_DIMENSIONS_CHANGED:
1247                 return TelephonyConstants.EVENT_VIDEO_PEER_DIMENSIONS_CHANGED;
1248             case VideoCallCallback.EVENT_VIDEO_QUALITY_CHANGED:
1249                 return TelephonyConstants.EVENT_VIDEO_QUALITY_CHANGED;
1250             case VideoCallCallback.EVENT_DATA_USAGE_CHANGED:
1251                 return TelephonyConstants.EVENT_VIDEO_DATA_USAGE_CHANGED;
1252             case VideoCallCallback.EVENT_CAMERA_CAPABILITIES_CHANGED:
1253                 return TelephonyConstants.EVENT_VIDEO_CAMERA_CAPABILITIES_CHANGED;
1254         }
1255         Log.d("getVideoCallCallbackEventString: event is invalid.");
1256         return TelephonyConstants.EVENT_VIDEO_INVALID;
1257     }
1258 
getCallStateString(int state)1259     public static String getCallStateString(int state) {
1260         switch (state) {
1261             case Call.STATE_NEW:
1262                 return TelephonyConstants.CALL_STATE_NEW;
1263             case Call.STATE_DIALING:
1264                 return TelephonyConstants.CALL_STATE_DIALING;
1265             case Call.STATE_RINGING:
1266                 return TelephonyConstants.CALL_STATE_RINGING;
1267             case Call.STATE_HOLDING:
1268                 return TelephonyConstants.CALL_STATE_HOLDING;
1269             case Call.STATE_ACTIVE:
1270                 return TelephonyConstants.CALL_STATE_ACTIVE;
1271             case Call.STATE_DISCONNECTED:
1272                 return TelephonyConstants.CALL_STATE_DISCONNECTED;
1273             case Call.STATE_PRE_DIAL_WAIT:
1274                 return TelephonyConstants.CALL_STATE_PRE_DIAL_WAIT;
1275             case Call.STATE_CONNECTING:
1276                 return TelephonyConstants.CALL_STATE_CONNECTING;
1277             case Call.STATE_DISCONNECTING:
1278                 return TelephonyConstants.CALL_STATE_DISCONNECTING;
1279             case STATE_INVALID:
1280                 return TelephonyConstants.CALL_STATE_INVALID;
1281             default:
1282                 return TelephonyConstants.CALL_STATE_UNKNOWN;
1283         }
1284     }
1285 
getAudioRoute(String audioRoute)1286     private static int getAudioRoute(String audioRoute) {
1287         switch (audioRoute.toUpperCase()) {
1288             case TelephonyConstants.AUDIO_ROUTE_BLUETOOTH:
1289                 return CallAudioState.ROUTE_BLUETOOTH;
1290             case TelephonyConstants.AUDIO_ROUTE_EARPIECE:
1291                 return CallAudioState.ROUTE_EARPIECE;
1292             case TelephonyConstants.AUDIO_ROUTE_SPEAKER:
1293                 return CallAudioState.ROUTE_SPEAKER;
1294             case TelephonyConstants.AUDIO_ROUTE_WIRED_HEADSET:
1295                 return CallAudioState.ROUTE_WIRED_HEADSET;
1296             case TelephonyConstants.AUDIO_ROUTE_WIRED_OR_EARPIECE:
1297                 return CallAudioState.ROUTE_WIRED_OR_EARPIECE;
1298             default:
1299                 return INVALID_AUDIO_ROUTE;
1300         }
1301     }
1302 
getAudioRouteString(int audioRoute)1303     public static String getAudioRouteString(int audioRoute) {
1304         return CallAudioState.audioRouteToString(audioRoute);
1305     }
1306 
getVideoCallSessionEventString(int event)1307     public static String getVideoCallSessionEventString(int event) {
1308 
1309         switch (event) {
1310             case Connection.VideoProvider.SESSION_EVENT_RX_PAUSE:
1311                 return TelephonyConstants.SESSION_EVENT_RX_PAUSE;
1312             case Connection.VideoProvider.SESSION_EVENT_RX_RESUME:
1313                 return TelephonyConstants.SESSION_EVENT_RX_RESUME;
1314             case Connection.VideoProvider.SESSION_EVENT_TX_START:
1315                 return TelephonyConstants.SESSION_EVENT_TX_START;
1316             case Connection.VideoProvider.SESSION_EVENT_TX_STOP:
1317                 return TelephonyConstants.SESSION_EVENT_TX_STOP;
1318             case Connection.VideoProvider.SESSION_EVENT_CAMERA_FAILURE:
1319                 return TelephonyConstants.SESSION_EVENT_CAMERA_FAILURE;
1320             case Connection.VideoProvider.SESSION_EVENT_CAMERA_READY:
1321                 return TelephonyConstants.SESSION_EVENT_CAMERA_READY;
1322             default:
1323                 return TelephonyConstants.SESSION_EVENT_UNKNOWN;
1324         }
1325     }
1326 
getCallCapabilityString(int capability)1327     public static String getCallCapabilityString(int capability) {
1328         switch (capability) {
1329             case Call.Details.CAPABILITY_HOLD:
1330                 return TelephonyConstants.CALL_CAPABILITY_HOLD;
1331             case Call.Details.CAPABILITY_SUPPORT_HOLD:
1332                 return TelephonyConstants.CALL_CAPABILITY_SUPPORT_HOLD;
1333             case Call.Details.CAPABILITY_MERGE_CONFERENCE:
1334                 return TelephonyConstants.CALL_CAPABILITY_MERGE_CONFERENCE;
1335             case Call.Details.CAPABILITY_SWAP_CONFERENCE:
1336                 return TelephonyConstants.CALL_CAPABILITY_SWAP_CONFERENCE;
1337             case Call.Details.CAPABILITY_UNUSED_1:
1338                 return TelephonyConstants.CALL_CAPABILITY_UNUSED_1;
1339             case Call.Details.CAPABILITY_RESPOND_VIA_TEXT:
1340                 return TelephonyConstants.CALL_CAPABILITY_RESPOND_VIA_TEXT;
1341             case Call.Details.CAPABILITY_MUTE:
1342                 return TelephonyConstants.CALL_CAPABILITY_MUTE;
1343             case Call.Details.CAPABILITY_MANAGE_CONFERENCE:
1344                 return TelephonyConstants.CALL_CAPABILITY_MANAGE_CONFERENCE;
1345             case Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_RX:
1346                 return TelephonyConstants.CALL_CAPABILITY_SUPPORTS_VT_LOCAL_RX;
1347             case Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_TX:
1348                 return TelephonyConstants.CALL_CAPABILITY_SUPPORTS_VT_LOCAL_TX;
1349             case Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL:
1350                 return TelephonyConstants.CALL_CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL;
1351             case Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_RX:
1352                 return TelephonyConstants.CALL_CAPABILITY_SUPPORTS_VT_REMOTE_RX;
1353             case Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_TX:
1354                 return TelephonyConstants.CALL_CAPABILITY_SUPPORTS_VT_REMOTE_TX;
1355             case Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL:
1356                 return TelephonyConstants.CALL_CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL;
1357             case Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE:
1358                 return TelephonyConstants.CALL_CAPABILITY_SEPARATE_FROM_CONFERENCE;
1359             case Call.Details.CAPABILITY_DISCONNECT_FROM_CONFERENCE:
1360                 return TelephonyConstants.CALL_CAPABILITY_DISCONNECT_FROM_CONFERENCE;
1361             case Call.Details.CAPABILITY_SPEED_UP_MT_AUDIO:
1362                 return TelephonyConstants.CALL_CAPABILITY_SPEED_UP_MT_AUDIO;
1363             case Call.Details.CAPABILITY_CAN_UPGRADE_TO_VIDEO:
1364                 return TelephonyConstants.CALL_CAPABILITY_CAN_UPGRADE_TO_VIDEO;
1365             case Call.Details.CAPABILITY_CAN_PAUSE_VIDEO:
1366                 return TelephonyConstants.CALL_CAPABILITY_CAN_PAUSE_VIDEO;
1367         }
1368         return TelephonyConstants.CALL_CAPABILITY_UNKOWN;
1369     }
1370 
getCallCapabilitiesString(int capabilities)1371     public static List<String> getCallCapabilitiesString(int capabilities) {
1372         final int[] capabilityConstants = new int[] {
1373                 Call.Details.CAPABILITY_HOLD,
1374                 Call.Details.CAPABILITY_SUPPORT_HOLD,
1375                 Call.Details.CAPABILITY_MERGE_CONFERENCE,
1376                 Call.Details.CAPABILITY_SWAP_CONFERENCE,
1377                 Call.Details.CAPABILITY_UNUSED_1,
1378                 Call.Details.CAPABILITY_RESPOND_VIA_TEXT,
1379                 Call.Details.CAPABILITY_MUTE,
1380                 Call.Details.CAPABILITY_MANAGE_CONFERENCE,
1381                 Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_RX,
1382                 Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_TX,
1383                 Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL,
1384                 Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_RX,
1385                 Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_TX,
1386                 Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL,
1387                 Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE,
1388                 Call.Details.CAPABILITY_DISCONNECT_FROM_CONFERENCE,
1389                 Call.Details.CAPABILITY_SPEED_UP_MT_AUDIO,
1390                 Call.Details.CAPABILITY_CAN_UPGRADE_TO_VIDEO,
1391                 Call.Details.CAPABILITY_CAN_PAUSE_VIDEO
1392         };
1393 
1394         List<String> capabilityList = new ArrayList<String>();
1395 
1396         for (int capability : capabilityConstants) {
1397             if ((capabilities & capability) == capability) {
1398                 capabilityList.add(getCallCapabilityString(capability));
1399             }
1400         }
1401         return capabilityList;
1402     }
1403 
getCallPropertyString(int property)1404     public static String getCallPropertyString(int property) {
1405 
1406         switch (property) {
1407             case Call.Details.PROPERTY_CONFERENCE:
1408                 return TelephonyConstants.CALL_PROPERTY_CONFERENCE;
1409             case Call.Details.PROPERTY_GENERIC_CONFERENCE:
1410                 return TelephonyConstants.CALL_PROPERTY_GENERIC_CONFERENCE;
1411             case Call.Details.PROPERTY_EMERGENCY_CALLBACK_MODE:
1412                 return TelephonyConstants.CALL_PROPERTY_EMERGENCY_CALLBACK_MODE;
1413             case Call.Details.PROPERTY_WIFI:
1414                 return TelephonyConstants.CALL_PROPERTY_WIFI;
1415             case Call.Details.PROPERTY_HIGH_DEF_AUDIO:
1416                 return TelephonyConstants.CALL_PROPERTY_HIGH_DEF_AUDIO;
1417             default:
1418                 return TelephonyConstants.CALL_PROPERTY_UNKNOWN;
1419         }
1420     }
1421 
getCallPropertiesString(int properties)1422     public static List<String> getCallPropertiesString(int properties) {
1423         final int[] propertyConstants = new int[] {
1424                 Call.Details.PROPERTY_CONFERENCE,
1425                 Call.Details.PROPERTY_GENERIC_CONFERENCE,
1426                 Call.Details.PROPERTY_EMERGENCY_CALLBACK_MODE,
1427                 Call.Details.PROPERTY_WIFI,
1428                 Call.Details.PROPERTY_HIGH_DEF_AUDIO
1429         };
1430 
1431         List<String> propertyList = new ArrayList<String>();
1432 
1433         for (int property : propertyConstants) {
1434             if ((properties & property) == property) {
1435                 propertyList.add(getCallPropertyString(property));
1436             }
1437         }
1438 
1439         return propertyList;
1440     }
1441 
getCallPresentationInfoString(int presentation)1442     public static String getCallPresentationInfoString(int presentation) {
1443         switch (presentation) {
1444             case TelecomManager.PRESENTATION_ALLOWED:
1445                 return TelephonyConstants.CALL_PRESENTATION_ALLOWED;
1446             case TelecomManager.PRESENTATION_RESTRICTED:
1447                 return TelephonyConstants.CALL_PRESENTATION_RESTRICTED;
1448             case TelecomManager.PRESENTATION_PAYPHONE:
1449                 return TelephonyConstants.CALL_PRESENTATION_PAYPHONE;
1450             default:
1451                 return TelephonyConstants.CALL_PRESENTATION_UNKNOWN;
1452         }
1453     }
1454 }
1455