Home | History | Annotate | Download | only in telecom
      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 mOwnerComponentName;
     39 
     40     /** Persists the specified parameters. */
     41     public InCallAdapter(CallsManager callsManager, CallIdMapper callIdMapper,
     42             TelecomSystem.SyncRoot lock, String ownerComponentName) {
     43         mCallsManager = callsManager;
     44         mCallIdMapper = callIdMapper;
     45         mLock = lock;
     46         mOwnerComponentName = ownerComponentName;
     47     }
     48 
     49     @Override
     50     public void answerCall(String callId, int videoState) {
     51         try {
     52             Log.startSession(LogUtils.Sessions.ICA_ANSWER_CALL, mOwnerComponentName);
     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
     73     public void deflectCall(String callId, Uri address) {
     74         try {
     75             Log.startSession(LogUtils.Sessions.ICA_DEFLECT_CALL, mOwnerComponentName);
     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
     96     public void rejectCall(String callId, boolean rejectWithMessage, String textMessage) {
     97         try {
     98             Log.startSession(LogUtils.Sessions.ICA_REJECT_CALL, mOwnerComponentName);
     99             // Check to make sure the in-call app's user isn't restricted from sending SMS. If so,
    100             // silently drop the outgoing message. Also drop message if the screen is locked.
    101             if (!mCallsManager.isReplyWithSmsAllowed(Binder.getCallingUid())) {
    102                 rejectWithMessage = false;
    103                 textMessage = null;
    104             }
    105             long token = Binder.clearCallingIdentity();
    106             try {
    107                 synchronized (mLock) {
    108                     Log.d(this, "rejectCall(%s,%b,%s)", callId, rejectWithMessage, textMessage);
    109                     Call call = mCallIdMapper.getCall(callId);
    110                     if (call != null) {
    111                         mCallsManager.rejectCall(call, rejectWithMessage, textMessage);
    112                     } else {
    113                         Log.w(this, "setRingback, unknown call id: %s", callId);
    114                     }
    115                 }
    116             } finally {
    117                 Binder.restoreCallingIdentity(token);
    118             }
    119         } finally {
    120             Log.endSession();
    121         }
    122     }
    123 
    124     @Override
    125     public void playDtmfTone(String callId, char digit) {
    126         try {
    127             Log.startSession("ICA.pDT", mOwnerComponentName);
    128             long token = Binder.clearCallingIdentity();
    129             try {
    130                 synchronized (mLock) {
    131                     Log.d(this, "playDtmfTone(%s,%c)", callId, digit);
    132                     Call call = mCallIdMapper.getCall(callId);
    133                     if (call != null) {
    134                         mCallsManager.playDtmfTone(call, digit);
    135                     } else {
    136                         Log.w(this, "playDtmfTone, unknown call id: %s", callId);
    137                     }
    138                 }
    139             } finally {
    140                 Binder.restoreCallingIdentity(token);
    141             }
    142         } finally {
    143             Log.endSession();
    144         }
    145     }
    146 
    147     @Override
    148     public void stopDtmfTone(String callId) {
    149         try {
    150             Log.startSession("ICA.sDT", mOwnerComponentName);
    151             long token = Binder.clearCallingIdentity();
    152             try {
    153                 synchronized (mLock) {
    154                     Log.d(this, "stopDtmfTone(%s)", callId);
    155                     Call call = mCallIdMapper.getCall(callId);
    156                     if (call != null) {
    157                         mCallsManager.stopDtmfTone(call);
    158                     } else {
    159                         Log.w(this, "stopDtmfTone, unknown call id: %s", callId);
    160                     }
    161                 }
    162             } finally {
    163                 Binder.restoreCallingIdentity(token);
    164             }
    165         } finally {
    166             Log.endSession();
    167         }
    168     }
    169 
    170     @Override
    171     public void postDialContinue(String callId, boolean proceed) {
    172         try {
    173             Log.startSession("ICA.pDC", mOwnerComponentName);
    174             long token = Binder.clearCallingIdentity();
    175             try {
    176                 synchronized (mLock) {
    177                     Log.d(this, "postDialContinue(%s)", callId);
    178                     Call call = mCallIdMapper.getCall(callId);
    179                     if (call != null) {
    180                         mCallsManager.postDialContinue(call, proceed);
    181                     } else {
    182                         Log.w(this, "postDialContinue, unknown call id: %s", callId);
    183                     }
    184                 }
    185             } finally {
    186                 Binder.restoreCallingIdentity(token);
    187             }
    188         } finally {
    189             Log.endSession();
    190         }
    191     }
    192 
    193     @Override
    194     public void disconnectCall(String callId) {
    195         try {
    196             Log.startSession(LogUtils.Sessions.ICA_DISCONNECT_CALL, mOwnerComponentName);
    197             long token = Binder.clearCallingIdentity();
    198             try {
    199                 synchronized (mLock) {
    200                     Log.v(this, "disconnectCall: %s", callId);
    201                     Call call = mCallIdMapper.getCall(callId);
    202                     if (call != null) {
    203                         mCallsManager.disconnectCall(call);
    204                     } else {
    205                         Log.w(this, "disconnectCall, unknown call id: %s", callId);
    206                     }
    207                 }
    208             } finally {
    209                 Binder.restoreCallingIdentity(token);
    210             }
    211         } finally {
    212             Log.endSession();
    213         }
    214     }
    215 
    216     @Override
    217     public void holdCall(String callId) {
    218         try {
    219             Log.startSession(LogUtils.Sessions.ICA_HOLD_CALL, mOwnerComponentName);
    220             long token = Binder.clearCallingIdentity();
    221             try {
    222                 synchronized (mLock) {
    223                     Call call = mCallIdMapper.getCall(callId);
    224                     if (call != null) {
    225                         mCallsManager.holdCall(call);
    226                     } else {
    227                         Log.w(this, "holdCall, unknown call id: %s", callId);
    228                     }
    229                 }
    230             } finally {
    231                 Binder.restoreCallingIdentity(token);
    232             }
    233         } finally {
    234             Log.endSession();
    235         }
    236     }
    237 
    238     @Override
    239     public void unholdCall(String callId) {
    240         try {
    241             Log.startSession(LogUtils.Sessions.ICA_UNHOLD_CALL, mOwnerComponentName);
    242             long token = Binder.clearCallingIdentity();
    243             try {
    244                 synchronized (mLock) {
    245                     Call call = mCallIdMapper.getCall(callId);
    246                     if (call != null) {
    247                         mCallsManager.unholdCall(call);
    248                     } else {
    249                         Log.w(this, "unholdCall, unknown call id: %s", callId);
    250                     }
    251                 }
    252             } finally {
    253                 Binder.restoreCallingIdentity(token);
    254             }
    255         } finally {
    256             Log.endSession();
    257         }
    258     }
    259 
    260     @Override
    261     public void phoneAccountSelected(String callId, PhoneAccountHandle accountHandle,
    262             boolean setDefault) {
    263         try {
    264             Log.startSession("ICA.pAS", mOwnerComponentName);
    265             long token = Binder.clearCallingIdentity();
    266             try {
    267                 synchronized (mLock) {
    268                     Call call = mCallIdMapper.getCall(callId);
    269                     if (call != null) {
    270                         mCallsManager.phoneAccountSelected(call, accountHandle, setDefault);
    271                     } else {
    272                         Log.w(this, "phoneAccountSelected, unknown call id: %s", callId);
    273                     }
    274                 }
    275             } finally {
    276                 Binder.restoreCallingIdentity(token);
    277             }
    278         } finally {
    279             Log.endSession();
    280         }
    281     }
    282 
    283     @Override
    284     public void mute(boolean shouldMute) {
    285         try {
    286             Log.startSession(LogUtils.Sessions.ICA_MUTE, mOwnerComponentName);
    287             long token = Binder.clearCallingIdentity();
    288             try {
    289                 synchronized (mLock) {
    290                     mCallsManager.mute(shouldMute);
    291                 }
    292             } finally {
    293                 Binder.restoreCallingIdentity(token);
    294             }
    295         } finally {
    296             Log.endSession();
    297         }
    298     }
    299 
    300     @Override
    301     public void setAudioRoute(int route, String bluetoothAddress) {
    302         try {
    303             Log.startSession(LogUtils.Sessions.ICA_SET_AUDIO_ROUTE, mOwnerComponentName);
    304             long token = Binder.clearCallingIdentity();
    305             try {
    306                 synchronized (mLock) {
    307                     mCallsManager.setAudioRoute(route, bluetoothAddress);
    308                 }
    309             } finally {
    310                 Binder.restoreCallingIdentity(token);
    311             }
    312         } finally {
    313             Log.endSession();
    314         }
    315     }
    316 
    317     @Override
    318     public void conference(String callId, String otherCallId) {
    319         try {
    320             Log.startSession(LogUtils.Sessions.ICA_CONFERENCE, mOwnerComponentName);
    321             long token = Binder.clearCallingIdentity();
    322             try {
    323                 synchronized (mLock) {
    324                     Call call = mCallIdMapper.getCall(callId);
    325                     Call otherCall = mCallIdMapper.getCall(otherCallId);
    326                     if (call != null && otherCall != null) {
    327                         mCallsManager.conference(call, otherCall);
    328                     } else {
    329                         Log.w(this, "conference, unknown call id: %s or %s", callId, otherCallId);
    330                     }
    331                 }
    332             } finally {
    333                 Binder.restoreCallingIdentity(token);
    334             }
    335         } finally {
    336             Log.endSession();
    337         }
    338     }
    339 
    340     @Override
    341     public void splitFromConference(String callId) {
    342         try {
    343             Log.startSession("ICA.sFC", mOwnerComponentName);
    344             long token = Binder.clearCallingIdentity();
    345             try {
    346                 synchronized (mLock) {
    347                     Call call = mCallIdMapper.getCall(callId);
    348                     if (call != null) {
    349                         call.splitFromConference();
    350                     } else {
    351                         Log.w(this, "splitFromConference, unknown call id: %s", callId);
    352                     }
    353                 }
    354             } finally {
    355                 Binder.restoreCallingIdentity(token);
    356             }
    357         } finally {
    358             Log.endSession();
    359         }
    360     }
    361 
    362     @Override
    363     public void mergeConference(String callId) {
    364         try {
    365             Log.startSession("ICA.mC", mOwnerComponentName);
    366             long token = Binder.clearCallingIdentity();
    367             try {
    368                 synchronized (mLock) {
    369                     Call call = mCallIdMapper.getCall(callId);
    370                     if (call != null) {
    371                         call.mergeConference();
    372                     } else {
    373                         Log.w(this, "mergeConference, unknown call id: %s", callId);
    374                     }
    375                 }
    376             } finally {
    377                 Binder.restoreCallingIdentity(token);
    378             }
    379         } finally {
    380             Log.endSession();
    381         }
    382     }
    383 
    384     @Override
    385     public void swapConference(String callId) {
    386         try {
    387             Log.startSession("ICA.sC", mOwnerComponentName);
    388             long token = Binder.clearCallingIdentity();
    389             try {
    390                 synchronized (mLock) {
    391                     Call call = mCallIdMapper.getCall(callId);
    392                     if (call != null) {
    393                         call.swapConference();
    394                     } else {
    395                         Log.w(this, "swapConference, unknown call id: %s", callId);
    396                     }
    397                 }
    398             } finally {
    399                 Binder.restoreCallingIdentity(token);
    400             }
    401         } finally {
    402             Log.endSession();
    403         }
    404     }
    405 
    406     @Override
    407     public void pullExternalCall(String callId) {
    408         try {
    409             Log.startSession("ICA.pEC", mOwnerComponentName);
    410             long token = Binder.clearCallingIdentity();
    411             try {
    412                 synchronized (mLock) {
    413                     Call call = mCallIdMapper.getCall(callId);
    414                     if (call != null) {
    415                         call.pullExternalCall();
    416                     } else {
    417                         Log.w(this, "pullExternalCall, unknown call id: %s", callId);
    418                     }
    419                 }
    420             } finally {
    421                 Binder.restoreCallingIdentity(token);
    422             }
    423         } finally {
    424             Log.endSession();
    425         }
    426     }
    427 
    428     @Override
    429     public void sendCallEvent(String callId, String event, int targetSdkVer, Bundle extras) {
    430         try {
    431             Log.startSession("ICA.sCE", mOwnerComponentName);
    432             long token = Binder.clearCallingIdentity();
    433             try {
    434                 synchronized (mLock) {
    435                     Call call = mCallIdMapper.getCall(callId);
    436                     if (call != null) {
    437                         call.sendCallEvent(event, targetSdkVer, extras);
    438                     } else {
    439                         Log.w(this, "sendCallEvent, unknown call id: %s", callId);
    440                     }
    441                 }
    442             } finally {
    443                 Binder.restoreCallingIdentity(token);
    444             }
    445         } finally {
    446             Log.endSession();
    447         }
    448     }
    449 
    450     @Override
    451     public void putExtras(String callId, Bundle extras) {
    452         try {
    453             Log.startSession("ICA.pE", mOwnerComponentName);
    454             long token = Binder.clearCallingIdentity();
    455             try {
    456                 synchronized (mLock) {
    457                     Call call = mCallIdMapper.getCall(callId);
    458                     if (call != null) {
    459                         call.putExtras(Call.SOURCE_INCALL_SERVICE, extras);
    460                     } else {
    461                         Log.w(this, "putExtras, unknown call id: %s", callId);
    462                     }
    463                 }
    464             } finally {
    465                 Binder.restoreCallingIdentity(token);
    466             }
    467         } finally {
    468             Log.endSession();
    469         }
    470     }
    471 
    472     @Override
    473     public void removeExtras(String callId, List<String> keys) {
    474         try {
    475             Log.startSession("ICA.rE", mOwnerComponentName);
    476             long token = Binder.clearCallingIdentity();
    477             try {
    478                 synchronized (mLock) {
    479                     Call call = mCallIdMapper.getCall(callId);
    480                     if (call != null) {
    481                         call.removeExtras(Call.SOURCE_INCALL_SERVICE, keys);
    482                     } else {
    483                         Log.w(this, "removeExtra, unknown call id: %s", callId);
    484                     }
    485                 }
    486             } finally {
    487                 Binder.restoreCallingIdentity(token);
    488             }
    489         } finally {
    490             Log.endSession();
    491         }
    492     }
    493 
    494     @Override
    495     public void turnOnProximitySensor() {
    496         try {
    497             Log.startSession("ICA.tOnPS", mOwnerComponentName);
    498             long token = Binder.clearCallingIdentity();
    499             try {
    500                 synchronized (mLock) {
    501                     mCallsManager.turnOnProximitySensor();
    502                 }
    503             } finally {
    504                 Binder.restoreCallingIdentity(token);
    505             }
    506         } finally {
    507             Log.endSession();
    508         }
    509     }
    510 
    511     @Override
    512     public void turnOffProximitySensor(boolean screenOnImmediately) {
    513         try {
    514             Log.startSession("ICA.tOffPS", mOwnerComponentName);
    515             long token = Binder.clearCallingIdentity();
    516             try {
    517                 synchronized (mLock) {
    518                     mCallsManager.turnOffProximitySensor(screenOnImmediately);
    519                 }
    520             } finally {
    521                 Binder.restoreCallingIdentity(token);
    522             }
    523         } finally {
    524              Log.endSession();
    525         }
    526     }
    527 
    528     @Override
    529     public void sendRttRequest(String callId) {
    530         try {
    531             Log.startSession("ICA.sRR");
    532             long token = Binder.clearCallingIdentity();
    533             try {
    534                 synchronized (mLock) {
    535                     Call call = mCallIdMapper.getCall(callId);
    536                     if (call != null) {
    537                         call.sendRttRequest();
    538                     } else {
    539                         Log.w(this, "stopRtt(): call %s not found", callId);
    540                     }
    541                 }
    542             } finally {
    543                 Binder.restoreCallingIdentity(token);
    544             }
    545         } finally {
    546             Log.endSession();
    547         }
    548     }
    549 
    550     @Override
    551     public void respondToRttRequest(String callId, int id, boolean accept) {
    552         try {
    553             Log.startSession("ICA.rTRR");
    554             long token = Binder.clearCallingIdentity();
    555             try {
    556                 synchronized (mLock) {
    557                     Call call = mCallIdMapper.getCall(callId);
    558                     if (call != null) {
    559                         call.handleRttRequestResponse(id, accept);
    560                     } else {
    561                         Log.w(this, "respondToRttRequest(): call %s not found", callId);
    562                     }
    563                 }
    564             } finally {
    565                 Binder.restoreCallingIdentity(token);
    566             }
    567         } finally {
    568             Log.endSession();
    569         }
    570     }
    571 
    572     @Override
    573     public void stopRtt(String callId) {
    574         try {
    575             Log.startSession("ICA.sRTT");
    576             long token = Binder.clearCallingIdentity();
    577             try {
    578                 synchronized (mLock) {
    579                     Call call = mCallIdMapper.getCall(callId);
    580                     if (call != null) {
    581                         call.stopRtt();
    582                     } else {
    583                         Log.w(this, "stopRtt(): call %s not found", callId);
    584                     }
    585                 }
    586             } finally {
    587                 Binder.restoreCallingIdentity(token);
    588             }
    589         } finally {
    590             Log.endSession();
    591         }
    592     }
    593 
    594     @Override
    595     public void setRttMode(String callId, int mode) {
    596         try {
    597             Log.startSession("ICA.sRM");
    598             long token = Binder.clearCallingIdentity();
    599             try {
    600                 synchronized (mLock) {
    601                     // TODO
    602                 }
    603             } finally {
    604                 Binder.restoreCallingIdentity(token);
    605             }
    606         } finally {
    607             Log.endSession();
    608         }
    609     }
    610 
    611     @Override
    612     public void handoverTo(String callId, PhoneAccountHandle destAcct, int videoState,
    613                            Bundle extras) {
    614         try {
    615             Log.startSession("ICA.hT", mOwnerComponentName);
    616             long token = Binder.clearCallingIdentity();
    617             try {
    618                 synchronized (mLock) {
    619                     Call call = mCallIdMapper.getCall(callId);
    620                     if (call != null) {
    621                         call.handoverTo(destAcct, videoState, extras);
    622                     } else {
    623                         Log.w(this, "handoverTo, unknown call id: %s", callId);
    624                     }
    625                 }
    626             } finally {
    627                 Binder.restoreCallingIdentity(token);
    628             }
    629         } finally {
    630             Log.endSession();
    631         }
    632     }
    633 }
    634