ConnectionServiceFixture.java revision 032f8e415661339bd1e9a2da5e295062a996a7f5
1/*
2 * Copyright (C) 2015 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
17package com.android.server.telecom.tests;
18
19import com.android.internal.telecom.IConnectionService;
20import com.android.internal.telecom.IConnectionServiceAdapter;
21import com.android.internal.telecom.IVideoProvider;
22import com.android.internal.telecom.RemoteServiceCallback;
23
24import junit.framework.TestCase;
25
26import org.mockito.Mockito;
27import org.mockito.invocation.InvocationOnMock;
28import org.mockito.stubbing.Answer;
29
30import android.content.ComponentName;
31import android.os.IBinder;
32import android.os.RemoteException;
33import android.telecom.Connection;
34import android.telecom.ConnectionRequest;
35import android.telecom.DisconnectCause;
36import android.telecom.ParcelableConference;
37import android.telecom.ParcelableConnection;
38import android.telecom.PhoneAccountHandle;
39import android.telecom.StatusHints;
40
41import java.util.ArrayList;
42import java.util.HashMap;
43import java.util.HashSet;
44import java.util.List;
45import java.util.Map;
46import java.util.Set;
47
48import static org.mockito.Matchers.any;
49import static org.mockito.Matchers.anyString;
50import static org.mockito.Mockito.doAnswer;
51import static org.mockito.Mockito.when;
52
53/**
54 * Controls a test {@link IConnectionService} as would be provided by a source of connectivity
55 * to the Telecom framework.
56 */
57public class ConnectionServiceFixture implements TestFixture<IConnectionService> {
58
59    private IConnectionService.Stub mConnectionService =
60            Mockito.mock(IConnectionService.Stub.class);
61
62    public class ConnectionInfo {
63        PhoneAccountHandle connectionManagerPhoneAccount;
64        String id;
65        boolean ringing;
66        ConnectionRequest request;
67        boolean isIncoming;
68        boolean isUnknown;
69        int state;
70        int addressPresentation;
71        int capabilities;
72        StatusHints statusHints;
73        DisconnectCause disconnectCause;
74        String conferenceId;
75        String callerDisplayName;
76        int callerDisplayNamePresentation;
77        final List<String> conferenceableConnectionIds = new ArrayList<>();
78        IVideoProvider videoProvider;
79        int videoState;
80        boolean isVoipAudioMode;
81    }
82
83    public class ConferenceInfo {
84        PhoneAccountHandle phoneAccount;
85        int state;
86        int capabilities;
87        final List<String> connectionIds = new ArrayList<>();
88        IVideoProvider videoProvider;
89        int videoState;
90        long connectTimeMillis;
91    }
92
93    public String mLatestConnectionId;
94    public final Set<IConnectionServiceAdapter> mConnectionServiceAdapters = new HashSet<>();
95    public final Map<String, ConnectionInfo> mConnectionById = new HashMap<>();
96    public final Map<String, ConferenceInfo> mConferenceById = new HashMap<>();
97    public final List<ComponentName> mRemoteConnectionServiceNames = new ArrayList<>();
98    public final List<IBinder> mRemoteConnectionServices = new ArrayList<>();
99
100    public ConnectionServiceFixture() throws Exception {
101        doAnswer(new Answer<Object>() {
102            @Override
103            public Object answer(InvocationOnMock invocation) throws Throwable {
104                IConnectionServiceAdapter a = (IConnectionServiceAdapter)
105                        invocation.getArguments()[0];
106                if (!mConnectionServiceAdapters.add(a)) {
107                    throw new RuntimeException("Adapter already added: " + a);
108                }
109                return null;
110            }
111        }).when(mConnectionService).addConnectionServiceAdapter(
112                any(IConnectionServiceAdapter.class));
113
114        doAnswer(new Answer<Object>() {
115            @Override
116            public Object answer(InvocationOnMock invocation) throws Throwable {
117                IConnectionServiceAdapter a = (IConnectionServiceAdapter)
118                        invocation.getArguments()[0];
119                if (!mConnectionServiceAdapters.remove(a)) {
120                    throw new RuntimeException("Adapter never added: " + a);
121                }
122                return null;
123            }
124        }).when(mConnectionService).removeConnectionServiceAdapter(
125                any(IConnectionServiceAdapter.class));
126
127        doAnswer(new Answer<Object>() {
128            @Override
129            public Object answer(InvocationOnMock invocation) throws Throwable {
130                String id = (String) invocation.getArguments()[1];
131                if (mConnectionById.containsKey(id)) {
132                    throw new RuntimeException("Connection already exists: " + id);
133                }
134                mLatestConnectionId = id;
135                ConnectionInfo c = new ConnectionInfo();
136                c.connectionManagerPhoneAccount = (PhoneAccountHandle) invocation.getArguments()[0];
137                c.id = id;
138                c.request = (ConnectionRequest) invocation.getArguments()[2];
139                c.isIncoming = (boolean) invocation.getArguments()[3];
140                c.isUnknown = (boolean) invocation.getArguments()[4];
141                mConnectionById.put(id, c);
142                return null;
143            }
144        }).when(mConnectionService).createConnection(
145                any(PhoneAccountHandle.class),
146                any(String.class),
147                any(ConnectionRequest.class),
148                any(Boolean.TYPE),
149                any(Boolean.TYPE));
150
151        when(mConnectionService.asBinder())
152                .thenReturn(mConnectionService);
153        when(mConnectionService.queryLocalInterface(anyString()))
154                .thenReturn(mConnectionService);
155    }
156
157    @Override
158    public IConnectionService getTestDouble() {
159        return mConnectionService;
160    }
161
162    public void sendHandleCreateConnectionComplete(String id) throws Exception {
163        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
164            a.handleCreateConnectionComplete(
165                    id,
166                    mConnectionById.get(id).request,
167                    parcelable(mConnectionById.get(id)));
168        }
169    }
170
171    public void sendSetActive(String id) throws Exception {
172        mConnectionById.get(id).state = Connection.STATE_ACTIVE;
173        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
174            a.setActive(id);
175        }
176    }
177
178    public void sendSetRinging(String id) throws Exception {
179        mConnectionById.get(id).state = Connection.STATE_RINGING;
180        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
181            a.setRinging(id);
182        }
183    }
184
185    public void sendSetDialing(String id) throws Exception {
186        mConnectionById.get(id).state = Connection.STATE_DIALING;
187        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
188            a.setDialing(id);
189        }
190    }
191
192    public void sendSetDisconnected(String id, int disconnectCause) throws Exception {
193        mConnectionById.get(id).state = Connection.STATE_DISCONNECTED;
194        mConnectionById.get(id).disconnectCause = new DisconnectCause(disconnectCause);
195        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
196            a.setDisconnected(id, mConnectionById.get(id).disconnectCause);
197        }
198    }
199
200    public void sendSetOnHold(String id) throws Exception {
201        mConnectionById.get(id).state = Connection.STATE_HOLDING;
202        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
203            a.setOnHold(id);
204        }
205    }
206
207    public void sendSetRingbackRequested(String id) throws Exception {
208        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
209            a.setRingbackRequested(id, mConnectionById.get(id).ringing);
210        }
211    }
212
213    public void sendSetConnectionCapabilities(String id) throws Exception {
214        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
215            a.setConnectionCapabilities(id, mConnectionById.get(id).capabilities);
216        }
217    }
218
219    public void sendSetIsConferenced(String id) throws Exception {
220        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
221            a.setIsConferenced(id, mConnectionById.get(id).conferenceId);
222        }
223    }
224
225    public void sendAddConferenceCall(String id) throws Exception {
226        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
227            a.addConferenceCall(id, parcelable(mConferenceById.get(id)));
228        }
229    }
230
231    public void sendRemoveCall(String id) throws Exception {
232        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
233            a.removeCall(id);
234        }
235    }
236
237    public void sendOnPostDialWait(String id, String remaining) throws Exception {
238        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
239            a.onPostDialWait(id, remaining);
240        }
241    }
242
243    public void sendOnPostDialChar(String id, char nextChar) throws Exception {
244        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
245            a.onPostDialChar(id, nextChar);
246        }
247    }
248
249    public void sendQueryRemoteConnectionServices() throws Exception {
250        mRemoteConnectionServices.clear();
251        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
252            a.queryRemoteConnectionServices(new RemoteServiceCallback.Stub() {
253                @Override
254                public void onError() throws RemoteException {
255                    throw new RuntimeException();
256                }
257
258                @Override
259                public void onResult(
260                        List<ComponentName> names,
261                        List<IBinder> services)
262                        throws RemoteException {
263                    TestCase.assertEquals(names.size(), services.size());
264                    mRemoteConnectionServiceNames.addAll(names);
265                    mRemoteConnectionServices.addAll(services);
266                }
267
268                @Override
269                public IBinder asBinder() {
270                    return this;
271                }
272            });
273        }
274    }
275
276    public void sendSetVideoProvider(String id) throws Exception {
277        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
278            a.setVideoProvider(id, mConnectionById.get(id).videoProvider);
279        }
280    }
281
282    public void sendSetVideoState(String id) throws Exception {
283        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
284            a.setVideoState(id, mConnectionById.get(id).videoState);
285        }
286    }
287
288    public void sendSetIsVoipAudioMode(String id) throws Exception {
289        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
290            a.setIsVoipAudioMode(id, mConnectionById.get(id).isVoipAudioMode);
291        }
292    }
293
294    public void sendSetStatusHints(String id) throws Exception {
295        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
296            a.setStatusHints(id, mConnectionById.get(id).statusHints);
297        }
298    }
299
300    public void sendSetAddress(String id) throws Exception {
301        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
302            a.setAddress(
303                    id,
304                    mConnectionById.get(id).request.getAddress(),
305                    mConnectionById.get(id).addressPresentation);
306        }
307    }
308
309    public void sendSetCallerDisplayName(String id) throws Exception {
310        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
311            a.setCallerDisplayName(
312                    id,
313                    mConnectionById.get(id).callerDisplayName,
314                    mConnectionById.get(id).callerDisplayNamePresentation);
315        }
316    }
317
318    public void sendSetConferenceableConnections(String id) throws Exception {
319        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
320            a.setConferenceableConnections(id, mConnectionById.get(id).conferenceableConnectionIds);
321        }
322    }
323
324    public void sendAddExistingConnection(String id) throws Exception {
325        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
326            a.addExistingConnection(id, parcelable(mConnectionById.get(id)));
327        }
328    }
329
330    private ParcelableConference parcelable(ConferenceInfo c) {
331        return new ParcelableConference(
332                c.phoneAccount,
333                c.state,
334                c.capabilities,
335                c.connectionIds,
336                c.videoProvider,
337                c.videoState,
338                c.connectTimeMillis);
339    }
340
341    private ParcelableConnection parcelable(ConnectionInfo c) {
342        return new ParcelableConnection(
343                c.request.getAccountHandle(),
344                c.state,
345                c.capabilities,
346                c.request.getAddress(),
347                c.addressPresentation,
348                c.callerDisplayName,
349                c.callerDisplayNamePresentation,
350                c.videoProvider,
351                c.videoState,
352                false, /* ringback requested */
353                false, /* voip audio mode */
354                c.statusHints,
355                c.disconnectCause,
356                c.conferenceableConnectionIds,
357                0 /* call substate */);
358    }
359}
360