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