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