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 android.telecom;
     18 
     19 import android.net.Uri;
     20 import android.os.IBinder.DeathRecipient;
     21 import android.os.RemoteException;
     22 
     23 import com.android.internal.telecom.IConnectionServiceAdapter;
     24 import com.android.internal.telecom.RemoteServiceCallback;
     25 
     26 import java.util.Collections;
     27 import java.util.Iterator;
     28 import java.util.List;
     29 import java.util.Set;
     30 import java.util.concurrent.ConcurrentHashMap;
     31 
     32 /**
     33  * Provides methods for IConnectionService implementations to interact with the system phone app.
     34  *
     35  * @hide
     36  */
     37 final class ConnectionServiceAdapter implements DeathRecipient {
     38     /**
     39      * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
     40      * load factor before resizing, 1 means we only expect a single thread to
     41      * access the map so make only a single shard
     42      */
     43     private final Set<IConnectionServiceAdapter> mAdapters = Collections.newSetFromMap(
     44             new ConcurrentHashMap<IConnectionServiceAdapter, Boolean>(8, 0.9f, 1));
     45 
     46     ConnectionServiceAdapter() {
     47     }
     48 
     49     void addAdapter(IConnectionServiceAdapter adapter) {
     50         if (mAdapters.add(adapter)) {
     51             try {
     52                 adapter.asBinder().linkToDeath(this, 0);
     53             } catch (RemoteException e) {
     54                 mAdapters.remove(adapter);
     55             }
     56         }
     57     }
     58 
     59     void removeAdapter(IConnectionServiceAdapter adapter) {
     60         if (adapter != null && mAdapters.remove(adapter)) {
     61             adapter.asBinder().unlinkToDeath(this, 0);
     62         }
     63     }
     64 
     65     /** ${inheritDoc} */
     66     @Override
     67     public void binderDied() {
     68         Iterator<IConnectionServiceAdapter> it = mAdapters.iterator();
     69         while (it.hasNext()) {
     70             IConnectionServiceAdapter adapter = it.next();
     71             if (!adapter.asBinder().isBinderAlive()) {
     72                 it.remove();
     73                 adapter.asBinder().unlinkToDeath(this, 0);
     74             }
     75         }
     76     }
     77 
     78     void handleCreateConnectionComplete(
     79             String id,
     80             ConnectionRequest request,
     81             ParcelableConnection connection) {
     82         for (IConnectionServiceAdapter adapter : mAdapters) {
     83             try {
     84                 adapter.handleCreateConnectionComplete(id, request, connection);
     85             } catch (RemoteException e) {
     86             }
     87         }
     88     }
     89 
     90     /**
     91      * Sets a call's state to active (e.g., an ongoing call where two parties can actively
     92      * communicate).
     93      *
     94      * @param callId The unique ID of the call whose state is changing to active.
     95      */
     96     void setActive(String callId) {
     97         for (IConnectionServiceAdapter adapter : mAdapters) {
     98             try {
     99                 adapter.setActive(callId);
    100             } catch (RemoteException e) {
    101             }
    102         }
    103     }
    104 
    105     /**
    106      * Sets a call's state to ringing (e.g., an inbound ringing call).
    107      *
    108      * @param callId The unique ID of the call whose state is changing to ringing.
    109      */
    110     void setRinging(String callId) {
    111         for (IConnectionServiceAdapter adapter : mAdapters) {
    112             try {
    113                 adapter.setRinging(callId);
    114             } catch (RemoteException e) {
    115             }
    116         }
    117     }
    118 
    119     /**
    120      * Sets a call's state to dialing (e.g., dialing an outbound call).
    121      *
    122      * @param callId The unique ID of the call whose state is changing to dialing.
    123      */
    124     void setDialing(String callId) {
    125         for (IConnectionServiceAdapter adapter : mAdapters) {
    126             try {
    127                 adapter.setDialing(callId);
    128             } catch (RemoteException e) {
    129             }
    130         }
    131     }
    132 
    133     /**
    134      * Sets a call's state to disconnected.
    135      *
    136      * @param callId The unique ID of the call whose state is changing to disconnected.
    137      * @param disconnectCause The reason for the disconnection, as described by
    138      *            {@link android.telecomm.DisconnectCause}.
    139      */
    140     void setDisconnected(String callId, DisconnectCause disconnectCause) {
    141         for (IConnectionServiceAdapter adapter : mAdapters) {
    142             try {
    143                 adapter.setDisconnected(callId, disconnectCause);
    144             } catch (RemoteException e) {
    145             }
    146         }
    147     }
    148 
    149     /**
    150      * Sets a call's state to be on hold.
    151      *
    152      * @param callId - The unique ID of the call whose state is changing to be on hold.
    153      */
    154     void setOnHold(String callId) {
    155         for (IConnectionServiceAdapter adapter : mAdapters) {
    156             try {
    157                 adapter.setOnHold(callId);
    158             } catch (RemoteException e) {
    159             }
    160         }
    161     }
    162 
    163     /**
    164      * Asks Telecom to start or stop a ringback tone for a call.
    165      *
    166      * @param callId The unique ID of the call whose ringback is being changed.
    167      * @param ringback Whether Telecom should start playing a ringback tone.
    168      */
    169     void setRingbackRequested(String callId, boolean ringback) {
    170         for (IConnectionServiceAdapter adapter : mAdapters) {
    171             try {
    172                 adapter.setRingbackRequested(callId, ringback);
    173             } catch (RemoteException e) {
    174             }
    175         }
    176     }
    177 
    178     void setConnectionCapabilities(String callId, int capabilities) {
    179         for (IConnectionServiceAdapter adapter : mAdapters) {
    180             try {
    181                 adapter.setConnectionCapabilities(callId, capabilities);
    182             } catch (RemoteException ignored) {
    183             }
    184         }
    185     }
    186 
    187     /**
    188      * Indicates whether or not the specified call is currently conferenced into the specified
    189      * conference call.
    190      *
    191      * @param callId The unique ID of the call being conferenced.
    192      * @param conferenceCallId The unique ID of the conference call. Null if call is not
    193      *            conferenced.
    194      */
    195     void setIsConferenced(String callId, String conferenceCallId) {
    196         for (IConnectionServiceAdapter adapter : mAdapters) {
    197             try {
    198                 Log.d(this, "sending connection %s with conference %s", callId, conferenceCallId);
    199                 adapter.setIsConferenced(callId, conferenceCallId);
    200             } catch (RemoteException ignored) {
    201             }
    202         }
    203     }
    204 
    205     /**
    206      * Indicates that the call no longer exists. Can be used with either a call or a conference
    207      * call.
    208      *
    209      * @param callId The unique ID of the call.
    210      */
    211     void removeCall(String callId) {
    212         for (IConnectionServiceAdapter adapter : mAdapters) {
    213             try {
    214                 adapter.removeCall(callId);
    215             } catch (RemoteException ignored) {
    216             }
    217         }
    218     }
    219 
    220     void onPostDialWait(String callId, String remaining) {
    221         for (IConnectionServiceAdapter adapter : mAdapters) {
    222             try {
    223                 adapter.onPostDialWait(callId, remaining);
    224             } catch (RemoteException ignored) {
    225             }
    226         }
    227     }
    228 
    229     void onPostDialChar(String callId, char nextChar) {
    230         for (IConnectionServiceAdapter adapter : mAdapters) {
    231             try {
    232                 adapter.onPostDialChar(callId, nextChar);
    233             } catch (RemoteException ignored) {
    234             }
    235         }
    236     }
    237 
    238     /**
    239      * Indicates that a new conference call has been created.
    240      *
    241      * @param callId The unique ID of the conference call.
    242      */
    243     void addConferenceCall(String callId, ParcelableConference parcelableConference) {
    244         for (IConnectionServiceAdapter adapter : mAdapters) {
    245             try {
    246                 adapter.addConferenceCall(callId, parcelableConference);
    247             } catch (RemoteException ignored) {
    248             }
    249         }
    250     }
    251 
    252     /**
    253      * Retrieves a list of remote connection services usable to place calls.
    254      */
    255     void queryRemoteConnectionServices(RemoteServiceCallback callback) {
    256         // Only supported when there is only one adapter.
    257         if (mAdapters.size() == 1) {
    258             try {
    259                 mAdapters.iterator().next().queryRemoteConnectionServices(callback);
    260             } catch (RemoteException e) {
    261                 Log.e(this, e, "Exception trying to query for remote CSs");
    262             }
    263         }
    264     }
    265 
    266     /**
    267      * Sets the call video provider for a call.
    268      *
    269      * @param callId The unique ID of the call to set with the given call video provider.
    270      * @param videoProvider The call video provider instance to set on the call.
    271      */
    272     void setVideoProvider(
    273             String callId, Connection.VideoProvider videoProvider) {
    274         for (IConnectionServiceAdapter adapter : mAdapters) {
    275             try {
    276                 adapter.setVideoProvider(
    277                         callId,
    278                         videoProvider == null ? null : videoProvider.getInterface());
    279             } catch (RemoteException e) {
    280             }
    281         }
    282     }
    283 
    284     /**
    285      * Requests that the framework use VOIP audio mode for this connection.
    286      *
    287      * @param callId The unique ID of the call to set with the given call video provider.
    288      * @param isVoip True if the audio mode is VOIP.
    289      */
    290     void setIsVoipAudioMode(String callId, boolean isVoip) {
    291         for (IConnectionServiceAdapter adapter : mAdapters) {
    292             try {
    293                 adapter.setIsVoipAudioMode(callId, isVoip);
    294             } catch (RemoteException e) {
    295             }
    296         }
    297     }
    298 
    299     void setStatusHints(String callId, StatusHints statusHints) {
    300         for (IConnectionServiceAdapter adapter : mAdapters) {
    301             try {
    302                 adapter.setStatusHints(callId, statusHints);
    303             } catch (RemoteException e) {
    304             }
    305         }
    306     }
    307 
    308     void setAddress(String callId, Uri address, int presentation) {
    309         for (IConnectionServiceAdapter adapter : mAdapters) {
    310             try {
    311                 adapter.setAddress(callId, address, presentation);
    312             } catch (RemoteException e) {
    313             }
    314         }
    315     }
    316 
    317     void setCallerDisplayName(String callId, String callerDisplayName, int presentation) {
    318         for (IConnectionServiceAdapter adapter : mAdapters) {
    319             try {
    320                 adapter.setCallerDisplayName(callId, callerDisplayName, presentation);
    321             } catch (RemoteException e) {
    322             }
    323         }
    324     }
    325 
    326     /**
    327      * Sets the video state associated with a call.
    328      *
    329      * Valid values: {@link VideoProfile.VideoState#AUDIO_ONLY},
    330      * {@link VideoProfile.VideoState#BIDIRECTIONAL},
    331      * {@link VideoProfile.VideoState#TX_ENABLED},
    332      * {@link VideoProfile.VideoState#RX_ENABLED}.
    333      *
    334      * @param callId The unique ID of the call to set the video state for.
    335      * @param videoState The video state.
    336      */
    337     void setVideoState(String callId, int videoState) {
    338         Log.v(this, "setVideoState: %d", videoState);
    339         for (IConnectionServiceAdapter adapter : mAdapters) {
    340             try {
    341                 adapter.setVideoState(callId, videoState);
    342             } catch (RemoteException ignored) {
    343             }
    344         }
    345     }
    346 
    347     void setConferenceableConnections(String callId, List<String> conferenceableCallIds) {
    348         Log.v(this, "setConferenceableConnections: %s, %s", callId, conferenceableCallIds);
    349         for (IConnectionServiceAdapter adapter : mAdapters) {
    350             try {
    351                 adapter.setConferenceableConnections(callId, conferenceableCallIds);
    352             } catch (RemoteException ignored) {
    353             }
    354         }
    355     }
    356 
    357     /**
    358      * Informs telecom of an existing connection which was added by the {@link ConnectionService}.
    359      *
    360      * @param callId The unique ID of the call being added.
    361      * @param connection The connection.
    362      */
    363     void addExistingConnection(String callId, ParcelableConnection connection) {
    364         Log.v(this, "addExistingConnection: %s", callId);
    365         for (IConnectionServiceAdapter adapter : mAdapters) {
    366             try {
    367                 adapter.addExistingConnection(callId, connection);
    368             } catch (RemoteException ignored) {
    369             }
    370         }
    371     }
    372 }
    373