1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.telecom;
18 
19 import android.net.Uri;
20 import android.os.Binder;
21 import android.os.Bundle;
22 import android.telecom.Log;
23 import android.telecom.PhoneAccountHandle;
24 
25 import com.android.internal.telecom.IInCallAdapter;
26 
27 import java.util.List;
28 
29 /**
30  * Receives call commands and updates from in-call app and passes them through to CallsManager.
31  * {@link InCallController} creates an instance of this class and passes it to the in-call app after
32  * binding to it. This adapter can receive commands and updates until the in-call app is unbound.
33  */
34 class InCallAdapter extends IInCallAdapter.Stub {
35     private final CallsManager mCallsManager;
36     private final CallIdMapper mCallIdMapper;
37     private final TelecomSystem.SyncRoot mLock;
38     private final String mOwnerPackageName;
39 
40     /** Persists the specified parameters. */
InCallAdapter(CallsManager callsManager, CallIdMapper callIdMapper, TelecomSystem.SyncRoot lock, String ownerPackageName)41     public InCallAdapter(CallsManager callsManager, CallIdMapper callIdMapper,
42             TelecomSystem.SyncRoot lock, String ownerPackageName) {
43         mCallsManager = callsManager;
44         mCallIdMapper = callIdMapper;
45         mLock = lock;
46         mOwnerPackageName = ownerPackageName;
47     }
48 
49     @Override
answerCall(String callId, int videoState)50     public void answerCall(String callId, int videoState) {
51         try {
52             Log.startSession(LogUtils.Sessions.ICA_ANSWER_CALL, mOwnerPackageName);
53             long token = Binder.clearCallingIdentity();
54             try {
55                 synchronized (mLock) {
56                     Log.d(this, "answerCall(%s,%d)", callId, videoState);
57                     Call call = mCallIdMapper.getCall(callId);
58                     if (call != null) {
59                         mCallsManager.answerCall(call, videoState);
60                     } else {
61                         Log.w(this, "answerCall, unknown call id: %s", callId);
62                     }
63                 }
64             } finally {
65                 Binder.restoreCallingIdentity(token);
66             }
67         } finally {
68             Log.endSession();
69         }
70     }
71 
72     @Override
deflectCall(String callId, Uri address)73     public void deflectCall(String callId, Uri address) {
74         try {
75             Log.startSession(LogUtils.Sessions.ICA_DEFLECT_CALL, mOwnerPackageName);
76             long token = Binder.clearCallingIdentity();
77             try {
78                 synchronized (mLock) {
79                     Log.i(this, "deflectCall - %s, %s ", callId, Log.pii(address));
80                     Call call = mCallIdMapper.getCall(callId);
81                     if (call != null) {
82                         mCallsManager.deflectCall(call, address);
83                     } else {
84                         Log.w(this, "deflectCall, unknown call id: %s", callId);
85                     }
86                 }
87             } finally {
88                 Binder.restoreCallingIdentity(token);
89             }
90         } finally {
91             Log.endSession();
92         }
93     }
94 
95     @Override
rejectCall(String callId, boolean rejectWithMessage, String textMessage)96     public void rejectCall(String callId, boolean rejectWithMessage, String textMessage) {
97         try {
98             Log.startSession(LogUtils.Sessions.ICA_REJECT_CALL, mOwnerPackageName);
99 
100             int callingUid = Binder.getCallingUid();
101             long token = Binder.clearCallingIdentity();
102             try {
103                 synchronized (mLock) {
104                     // Check to make sure the in-call app's user isn't restricted from sending SMS.
105                     // If so, silently drop the outgoing message. Also drop message if the screen is
106                     // locked.
107                     if (!mCallsManager.isReplyWithSmsAllowed(callingUid)) {
108                         rejectWithMessage = false;
109                         textMessage = null;
110                     }
111 
112                     Log.d(this, "rejectCall(%s,%b,%s)", callId, rejectWithMessage, textMessage);
113                     Call call = mCallIdMapper.getCall(callId);
114                     if (call != null) {
115                         mCallsManager.rejectCall(call, rejectWithMessage, textMessage);
116                     } else {
117                         Log.w(this, "setRingback, unknown call id: %s", callId);
118                     }
119                 }
120             } finally {
121                 Binder.restoreCallingIdentity(token);
122             }
123         } finally {
124             Log.endSession();
125         }
126     }
127 
128     @Override
rejectCallWithReason(String callId, @android.telecom.Call.RejectReason int rejectReason)129     public void rejectCallWithReason(String callId,
130             @android.telecom.Call.RejectReason int rejectReason) {
131         try {
132             Log.startSession(LogUtils.Sessions.ICA_REJECT_CALL, mOwnerPackageName);
133 
134             int callingUid = Binder.getCallingUid();
135             long token = Binder.clearCallingIdentity();
136             try {
137                 synchronized (mLock) {
138                     Log.d(this, "rejectCallWithReason(%s,%d)", callId, rejectReason);
139                     Call call = mCallIdMapper.getCall(callId);
140                     if (call != null) {
141                         mCallsManager.rejectCall(call, rejectReason);
142                     } else {
143                         Log.w(this, "rejectCallWithReason, unknown call id: %s", callId);
144                     }
145                 }
146             } finally {
147                 Binder.restoreCallingIdentity(token);
148             }
149         } finally {
150             Log.endSession();
151         }
152     }
153 
transferCall(String callId, Uri targetNumber, boolean isConfirmationRequired)154     public void transferCall(String callId, Uri targetNumber, boolean isConfirmationRequired) {
155         try {
156             Log.startSession(LogUtils.Sessions.ICA_TRANSFER_CALL, mOwnerPackageName);
157             long token = Binder.clearCallingIdentity();
158             try {
159                 synchronized (mLock) {
160                     Log.i(this, "transferCall - %s, %s, %b", callId, Log.pii(targetNumber),
161                             isConfirmationRequired);
162                     Call call = mCallIdMapper.getCall(callId);
163                     if (call != null) {
164                         mCallsManager.transferCall(call, targetNumber, isConfirmationRequired);
165                     } else {
166                         Log.w(this, "transferCall, unknown call id: %s", callId);
167                     }
168                 }
169             } finally {
170                 Binder.restoreCallingIdentity(token);
171             }
172         } finally {
173             Log.endSession();
174         }
175     }
176 
177     @Override
consultativeTransfer(String callId, String otherCallId)178     public void consultativeTransfer(String callId, String otherCallId) {
179         try {
180             Log.startSession(LogUtils.Sessions.ICA_CONSULTATIVE_TRANSFER, mOwnerPackageName);
181             long token = Binder.clearCallingIdentity();
182             try {
183                 synchronized (mLock) {
184                     Log.i(this, "consultativeTransfer - %s, %s", callId, otherCallId);
185                     Call call = mCallIdMapper.getCall(callId);
186                     Call otherCall = mCallIdMapper.getCall(otherCallId);
187                     if (call != null && otherCall != null) {
188                         mCallsManager.transferCall(call, otherCall);
189                     } else {
190                         Log.w(this, "consultativeTransfer, unknown call id: %s or %s",
191                                 callId, otherCallId);
192                     }
193                 }
194             } finally {
195                 Binder.restoreCallingIdentity(token);
196             }
197         } finally {
198             Log.endSession();
199         }
200     }
201 
202     @Override
playDtmfTone(String callId, char digit)203     public void playDtmfTone(String callId, char digit) {
204         try {
205             Log.startSession("ICA.pDT", mOwnerPackageName);
206             long token = Binder.clearCallingIdentity();
207             try {
208                 synchronized (mLock) {
209                     Log.d(this, "playDtmfTone(%s,%c)", callId, digit);
210                     Call call = mCallIdMapper.getCall(callId);
211                     if (call != null) {
212                         mCallsManager.playDtmfTone(call, digit);
213                     } else {
214                         Log.w(this, "playDtmfTone, unknown call id: %s", callId);
215                     }
216                 }
217             } finally {
218                 Binder.restoreCallingIdentity(token);
219             }
220         } finally {
221             Log.endSession();
222         }
223     }
224 
225     @Override
stopDtmfTone(String callId)226     public void stopDtmfTone(String callId) {
227         try {
228             Log.startSession("ICA.sDT", mOwnerPackageName);
229             long token = Binder.clearCallingIdentity();
230             try {
231                 synchronized (mLock) {
232                     Log.d(this, "stopDtmfTone(%s)", callId);
233                     Call call = mCallIdMapper.getCall(callId);
234                     if (call != null) {
235                         mCallsManager.stopDtmfTone(call);
236                     } else {
237                         Log.w(this, "stopDtmfTone, unknown call id: %s", callId);
238                     }
239                 }
240             } finally {
241                 Binder.restoreCallingIdentity(token);
242             }
243         } finally {
244             Log.endSession();
245         }
246     }
247 
248     @Override
postDialContinue(String callId, boolean proceed)249     public void postDialContinue(String callId, boolean proceed) {
250         try {
251             Log.startSession("ICA.pDC", mOwnerPackageName);
252             long token = Binder.clearCallingIdentity();
253             try {
254                 synchronized (mLock) {
255                     Log.d(this, "postDialContinue(%s)", callId);
256                     Call call = mCallIdMapper.getCall(callId);
257                     if (call != null) {
258                         mCallsManager.postDialContinue(call, proceed);
259                     } else {
260                         Log.w(this, "postDialContinue, unknown call id: %s", callId);
261                     }
262                 }
263             } finally {
264                 Binder.restoreCallingIdentity(token);
265             }
266         } finally {
267             Log.endSession();
268         }
269     }
270 
271     @Override
disconnectCall(String callId)272     public void disconnectCall(String callId) {
273         try {
274             Log.startSession(LogUtils.Sessions.ICA_DISCONNECT_CALL, mOwnerPackageName);
275             long token = Binder.clearCallingIdentity();
276             try {
277                 synchronized (mLock) {
278                     Log.v(this, "disconnectCall: %s", callId);
279                     Call call = mCallIdMapper.getCall(callId);
280                     if (call != null) {
281                         mCallsManager.disconnectCall(call);
282                     } else {
283                         Log.w(this, "disconnectCall, unknown call id: %s", callId);
284                     }
285                 }
286             } finally {
287                 Binder.restoreCallingIdentity(token);
288             }
289         } finally {
290             Log.endSession();
291         }
292     }
293 
294     @Override
holdCall(String callId)295     public void holdCall(String callId) {
296         try {
297             Log.startSession(LogUtils.Sessions.ICA_HOLD_CALL, mOwnerPackageName);
298             long token = Binder.clearCallingIdentity();
299             try {
300                 synchronized (mLock) {
301                     Call call = mCallIdMapper.getCall(callId);
302                     if (call != null) {
303                         mCallsManager.holdCall(call);
304                     } else {
305                         Log.w(this, "holdCall, unknown call id: %s", callId);
306                     }
307                 }
308             } finally {
309                 Binder.restoreCallingIdentity(token);
310             }
311         } finally {
312             Log.endSession();
313         }
314     }
315 
316     @Override
unholdCall(String callId)317     public void unholdCall(String callId) {
318         try {
319             Log.startSession(LogUtils.Sessions.ICA_UNHOLD_CALL, mOwnerPackageName);
320             long token = Binder.clearCallingIdentity();
321             try {
322                 synchronized (mLock) {
323                     Call call = mCallIdMapper.getCall(callId);
324                     if (call != null) {
325                         mCallsManager.unholdCall(call);
326                     } else {
327                         Log.w(this, "unholdCall, unknown call id: %s", callId);
328                     }
329                 }
330             } finally {
331                 Binder.restoreCallingIdentity(token);
332             }
333         } finally {
334             Log.endSession();
335         }
336     }
337 
338     @Override
phoneAccountSelected(String callId, PhoneAccountHandle accountHandle, boolean setDefault)339     public void phoneAccountSelected(String callId, PhoneAccountHandle accountHandle,
340             boolean setDefault) {
341         try {
342             Log.startSession("ICA.pAS", mOwnerPackageName);
343             long token = Binder.clearCallingIdentity();
344             try {
345                 synchronized (mLock) {
346                     Call call = mCallIdMapper.getCall(callId);
347                     if (call != null) {
348                         mCallsManager.phoneAccountSelected(call, accountHandle, setDefault);
349                     } else {
350                         Log.w(this, "phoneAccountSelected, unknown call id: %s", callId);
351                     }
352                 }
353             } finally {
354                 Binder.restoreCallingIdentity(token);
355             }
356         } finally {
357             Log.endSession();
358         }
359     }
360 
361     @Override
mute(boolean shouldMute)362     public void mute(boolean shouldMute) {
363         try {
364             Log.startSession(LogUtils.Sessions.ICA_MUTE, mOwnerPackageName);
365             long token = Binder.clearCallingIdentity();
366             try {
367                 synchronized (mLock) {
368                     mCallsManager.mute(shouldMute);
369                 }
370             } finally {
371                 Binder.restoreCallingIdentity(token);
372             }
373         } finally {
374             Log.endSession();
375         }
376     }
377 
378     @Override
setAudioRoute(int route, String bluetoothAddress)379     public void setAudioRoute(int route, String bluetoothAddress) {
380         try {
381             Log.startSession(LogUtils.Sessions.ICA_SET_AUDIO_ROUTE, mOwnerPackageName);
382             long token = Binder.clearCallingIdentity();
383             try {
384                 synchronized (mLock) {
385                     mCallsManager.setAudioRoute(route, bluetoothAddress);
386                 }
387             } finally {
388                 Binder.restoreCallingIdentity(token);
389             }
390         } finally {
391             Log.endSession();
392         }
393     }
394 
395     @Override
enterBackgroundAudioProcessing(String callId)396     public void enterBackgroundAudioProcessing(String callId) {
397         try {
398             Log.startSession(LogUtils.Sessions.ICA_ENTER_AUDIO_PROCESSING, mOwnerPackageName);
399             // TODO: enforce the extra permission.
400             Binder.withCleanCallingIdentity(() -> {
401                 synchronized (mLock) {
402                     Call call = mCallIdMapper.getCall(callId);
403                     if (call != null) {
404                         mCallsManager.enterBackgroundAudioProcessing(call, mOwnerPackageName);
405                     } else {
406                         Log.w(this, "enterBackgroundAudioProcessing, unknown call id: %s", callId);
407                     }
408                 }
409             });
410         } finally {
411             Log.endSession();
412         }
413     }
414 
415     @Override
exitBackgroundAudioProcessing(String callId, boolean shouldRing)416     public void exitBackgroundAudioProcessing(String callId, boolean shouldRing) {
417         try {
418             Log.startSession(LogUtils.Sessions.ICA_EXIT_AUDIO_PROCESSING, mOwnerPackageName);
419             Binder.withCleanCallingIdentity(() -> {
420                 synchronized (mLock) {
421                     Call call = mCallIdMapper.getCall(callId);
422                     if (call != null) {
423                         mCallsManager.exitBackgroundAudioProcessing(call, shouldRing);
424                     } else {
425                         Log.w(InCallAdapter.this,
426                                 "exitBackgroundAudioProcessing, unknown call id: %s", callId);
427                     }
428                 }
429             });
430         } finally {
431             Log.endSession();
432         }
433     }
434 
435     @Override
conference(String callId, String otherCallId)436     public void conference(String callId, String otherCallId) {
437         try {
438             Log.startSession(LogUtils.Sessions.ICA_CONFERENCE, mOwnerPackageName);
439             long token = Binder.clearCallingIdentity();
440             try {
441                 synchronized (mLock) {
442                     Call call = mCallIdMapper.getCall(callId);
443                     Call otherCall = mCallIdMapper.getCall(otherCallId);
444                     if (call != null && otherCall != null) {
445                         mCallsManager.conference(call, otherCall);
446                     } else {
447                         Log.w(this, "conference, unknown call id: %s or %s", callId, otherCallId);
448                     }
449                 }
450             } finally {
451                 Binder.restoreCallingIdentity(token);
452             }
453         } finally {
454             Log.endSession();
455         }
456     }
457 
458     @Override
splitFromConference(String callId)459     public void splitFromConference(String callId) {
460         try {
461             Log.startSession("ICA.sFC", mOwnerPackageName);
462             long token = Binder.clearCallingIdentity();
463             try {
464                 synchronized (mLock) {
465                     Call call = mCallIdMapper.getCall(callId);
466                     if (call != null) {
467                         call.splitFromConference();
468                     } else {
469                         Log.w(this, "splitFromConference, unknown call id: %s", callId);
470                     }
471                 }
472             } finally {
473                 Binder.restoreCallingIdentity(token);
474             }
475         } finally {
476             Log.endSession();
477         }
478     }
479 
480     @Override
mergeConference(String callId)481     public void mergeConference(String callId) {
482         try {
483             Log.startSession("ICA.mC", mOwnerPackageName);
484             long token = Binder.clearCallingIdentity();
485             try {
486                 synchronized (mLock) {
487                     Call call = mCallIdMapper.getCall(callId);
488                     if (call != null) {
489                         call.mergeConference();
490                     } else {
491                         Log.w(this, "mergeConference, unknown call id: %s", callId);
492                     }
493                 }
494             } finally {
495                 Binder.restoreCallingIdentity(token);
496             }
497         } finally {
498             Log.endSession();
499         }
500     }
501 
502     @Override
swapConference(String callId)503     public void swapConference(String callId) {
504         try {
505             Log.startSession("ICA.sC", mOwnerPackageName);
506             long token = Binder.clearCallingIdentity();
507             try {
508                 synchronized (mLock) {
509                     Call call = mCallIdMapper.getCall(callId);
510                     if (call != null) {
511                         call.swapConference();
512                     } else {
513                         Log.w(this, "swapConference, unknown call id: %s", callId);
514                     }
515                 }
516             } finally {
517                 Binder.restoreCallingIdentity(token);
518             }
519         } finally {
520             Log.endSession();
521         }
522     }
523 
524     @Override
addConferenceParticipants(String callId, List<Uri> participants)525     public void addConferenceParticipants(String callId, List<Uri> participants) {
526         try {
527             Log.startSession("ICA.aCP", mOwnerPackageName);
528             long token = Binder.clearCallingIdentity();
529             try {
530                 synchronized (mLock) {
531                     Call call = mCallIdMapper.getCall(callId);
532                     if (call != null) {
533                         call.addConferenceParticipants(participants);
534                     } else {
535                         Log.w(this, "addConferenceParticipants, unknown call id: %s", callId);
536                     }
537                 }
538             } finally {
539                 Binder.restoreCallingIdentity(token);
540             }
541         } finally {
542             Log.endSession();
543         }
544     }
545 
546 
547     @Override
pullExternalCall(String callId)548     public void pullExternalCall(String callId) {
549         try {
550             Log.startSession("ICA.pEC", mOwnerPackageName);
551             long token = Binder.clearCallingIdentity();
552             try {
553                 synchronized (mLock) {
554                     Call call = mCallIdMapper.getCall(callId);
555                     if (call != null) {
556                         call.pullExternalCall();
557                     } else {
558                         Log.w(this, "pullExternalCall, unknown call id: %s", callId);
559                     }
560                 }
561             } finally {
562                 Binder.restoreCallingIdentity(token);
563             }
564         } finally {
565             Log.endSession();
566         }
567     }
568 
569     @Override
sendCallEvent(String callId, String event, int targetSdkVer, Bundle extras)570     public void sendCallEvent(String callId, String event, int targetSdkVer, Bundle extras) {
571         try {
572             Log.startSession("ICA.sCE", mOwnerPackageName);
573             long token = Binder.clearCallingIdentity();
574             try {
575                 synchronized (mLock) {
576                     Call call = mCallIdMapper.getCall(callId);
577                     if (call != null) {
578                         call.sendCallEvent(event, targetSdkVer, extras);
579                     } else {
580                         Log.w(this, "sendCallEvent, unknown call id: %s", callId);
581                     }
582                 }
583             } finally {
584                 Binder.restoreCallingIdentity(token);
585             }
586         } finally {
587             Log.endSession();
588         }
589     }
590 
591     @Override
putExtras(String callId, Bundle extras)592     public void putExtras(String callId, Bundle extras) {
593         try {
594             Log.startSession("ICA.pE", mOwnerPackageName);
595             long token = Binder.clearCallingIdentity();
596             try {
597                 synchronized (mLock) {
598                     Call call = mCallIdMapper.getCall(callId);
599                     if (call != null) {
600                         call.putExtras(Call.SOURCE_INCALL_SERVICE, extras);
601                     } else {
602                         Log.w(this, "putExtras, unknown call id: %s", callId);
603                     }
604                 }
605             } finally {
606                 Binder.restoreCallingIdentity(token);
607             }
608         } finally {
609             Log.endSession();
610         }
611     }
612 
613     @Override
removeExtras(String callId, List<String> keys)614     public void removeExtras(String callId, List<String> keys) {
615         try {
616             Log.startSession("ICA.rE", mOwnerPackageName);
617             long token = Binder.clearCallingIdentity();
618             try {
619                 synchronized (mLock) {
620                     Call call = mCallIdMapper.getCall(callId);
621                     if (call != null) {
622                         call.removeExtras(Call.SOURCE_INCALL_SERVICE, keys);
623                     } else {
624                         Log.w(this, "removeExtra, unknown call id: %s", callId);
625                     }
626                 }
627             } finally {
628                 Binder.restoreCallingIdentity(token);
629             }
630         } finally {
631             Log.endSession();
632         }
633     }
634 
635     @Override
turnOnProximitySensor()636     public void turnOnProximitySensor() {
637         try {
638             Log.startSession("ICA.tOnPS", mOwnerPackageName);
639             long token = Binder.clearCallingIdentity();
640             try {
641                 synchronized (mLock) {
642                     mCallsManager.turnOnProximitySensor();
643                 }
644             } finally {
645                 Binder.restoreCallingIdentity(token);
646             }
647         } finally {
648             Log.endSession();
649         }
650     }
651 
652     @Override
turnOffProximitySensor(boolean screenOnImmediately)653     public void turnOffProximitySensor(boolean screenOnImmediately) {
654         try {
655             Log.startSession("ICA.tOffPS", mOwnerPackageName);
656             long token = Binder.clearCallingIdentity();
657             try {
658                 synchronized (mLock) {
659                     mCallsManager.turnOffProximitySensor(screenOnImmediately);
660                 }
661             } finally {
662                 Binder.restoreCallingIdentity(token);
663             }
664         } finally {
665              Log.endSession();
666         }
667     }
668 
669     @Override
sendRttRequest(String callId)670     public void sendRttRequest(String callId) {
671         try {
672             Log.startSession("ICA.sRR");
673             long token = Binder.clearCallingIdentity();
674             try {
675                 synchronized (mLock) {
676                     Call call = mCallIdMapper.getCall(callId);
677                     if (call != null) {
678                         call.sendRttRequest();
679                     } else {
680                         Log.w(this, "stopRtt(): call %s not found", callId);
681                     }
682                 }
683             } finally {
684                 Binder.restoreCallingIdentity(token);
685             }
686         } finally {
687             Log.endSession();
688         }
689     }
690 
691     @Override
respondToRttRequest(String callId, int id, boolean accept)692     public void respondToRttRequest(String callId, int id, boolean accept) {
693         try {
694             Log.startSession("ICA.rTRR");
695             long token = Binder.clearCallingIdentity();
696             try {
697                 synchronized (mLock) {
698                     Call call = mCallIdMapper.getCall(callId);
699                     if (call != null) {
700                         call.handleRttRequestResponse(id, accept);
701                     } else {
702                         Log.w(this, "respondToRttRequest(): call %s not found", callId);
703                     }
704                 }
705             } finally {
706                 Binder.restoreCallingIdentity(token);
707             }
708         } finally {
709             Log.endSession();
710         }
711     }
712 
713     @Override
stopRtt(String callId)714     public void stopRtt(String callId) {
715         try {
716             Log.startSession("ICA.sRTT");
717             long token = Binder.clearCallingIdentity();
718             try {
719                 synchronized (mLock) {
720                     Call call = mCallIdMapper.getCall(callId);
721                     if (call != null) {
722                         call.stopRtt();
723                     } else {
724                         Log.w(this, "stopRtt(): call %s not found", callId);
725                     }
726                 }
727             } finally {
728                 Binder.restoreCallingIdentity(token);
729             }
730         } finally {
731             Log.endSession();
732         }
733     }
734 
735     @Override
setRttMode(String callId, int mode)736     public void setRttMode(String callId, int mode) {
737         try {
738             Log.startSession("ICA.sRM");
739             long token = Binder.clearCallingIdentity();
740             try {
741                 synchronized (mLock) {
742                     // TODO
743                 }
744             } finally {
745                 Binder.restoreCallingIdentity(token);
746             }
747         } finally {
748             Log.endSession();
749         }
750     }
751 
752     @Override
handoverTo(String callId, PhoneAccountHandle destAcct, int videoState, Bundle extras)753     public void handoverTo(String callId, PhoneAccountHandle destAcct, int videoState,
754                            Bundle extras) {
755         try {
756             Log.startSession("ICA.hT", mOwnerPackageName);
757             long token = Binder.clearCallingIdentity();
758             try {
759                 synchronized (mLock) {
760                     Call call = mCallIdMapper.getCall(callId);
761                     if (call != null) {
762                         call.handoverTo(destAcct, videoState, extras);
763                     } else {
764                         Log.w(this, "handoverTo, unknown call id: %s", callId);
765                     }
766                 }
767             } finally {
768                 Binder.restoreCallingIdentity(token);
769             }
770         } finally {
771             Log.endSession();
772         }
773     }
774 }
775