ConnectionServiceFixture.java revision 2c93c50e5be7d85b78c4af15aaa10e44f0bcdf3e
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.Bundle;
31import android.os.IBinder;
32import android.os.IInterface;
33import android.os.RemoteException;
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            c.capabilities |= Connection.CAPABILITY_HOLD | Connection.CAPABILITY_SUPPORT_HOLD;
94            mConnectionById.put(id, c);
95        }
96
97        @Override
98        public void abort(String callId) throws RemoteException { }
99
100        @Override
101        public void answerVideo(String callId, int videoState) throws RemoteException { }
102
103        @Override
104        public void answer(String callId) throws RemoteException { }
105
106        @Override
107        public void reject(String callId) throws RemoteException { }
108
109        @Override
110        public void rejectWithMessage(String callId, String message) throws RemoteException { }
111
112        @Override
113        public void disconnect(String callId) throws RemoteException { }
114
115        @Override
116        public void hold(String callId) throws RemoteException { }
117
118        @Override
119        public void unhold(String callId) throws RemoteException { }
120
121        @Override
122        public void onCallAudioStateChanged(String activeCallId, CallAudioState audioState)
123                throws RemoteException { }
124
125        @Override
126        public void playDtmfTone(String callId, char digit) throws RemoteException { }
127
128        @Override
129        public void stopDtmfTone(String callId) throws RemoteException { }
130
131        @Override
132        public void conference(String conferenceCallId, String callId) throws RemoteException { }
133
134        @Override
135        public void splitFromConference(String callId) throws RemoteException { }
136
137        @Override
138        public void mergeConference(String conferenceCallId) throws RemoteException { }
139
140        @Override
141        public void swapConference(String conferenceCallId) throws RemoteException { }
142
143        @Override
144        public void onPostDialContinue(String callId, boolean proceed) throws RemoteException { }
145
146        @Override
147        public IBinder asBinder() {
148            return this;
149        }
150
151        @Override
152        public IInterface queryLocalInterface(String descriptor) {
153            return this;
154        }
155    };
156
157    private IConnectionService.Stub mConnectionService = new FakeConnectionService();
158    private IConnectionService.Stub mConnectionServiceSpy = Mockito.spy(mConnectionService);
159
160    public class ConnectionInfo {
161        PhoneAccountHandle connectionManagerPhoneAccount;
162        String id;
163        boolean ringing;
164        ConnectionRequest request;
165        boolean isIncoming;
166        boolean isUnknown;
167        int state;
168        int addressPresentation;
169        int capabilities;
170        StatusHints statusHints;
171        DisconnectCause disconnectCause;
172        String conferenceId;
173        String callerDisplayName;
174        int callerDisplayNamePresentation;
175        final List<String> conferenceableConnectionIds = new ArrayList<>();
176        IVideoProvider videoProvider;
177        int videoState;
178        boolean isVoipAudioMode;
179        Bundle extras;
180    }
181
182    public class ConferenceInfo {
183        PhoneAccountHandle phoneAccount;
184        int state;
185        int capabilities;
186        final List<String> connectionIds = new ArrayList<>();
187        IVideoProvider videoProvider;
188        int videoState;
189        long connectTimeMillis;
190        StatusHints statusHints;
191        Bundle extras;
192    }
193
194    public String mLatestConnectionId;
195    public final Set<IConnectionServiceAdapter> mConnectionServiceAdapters = new HashSet<>();
196    public final Map<String, ConnectionInfo> mConnectionById = new HashMap<>();
197    public final Map<String, ConferenceInfo> mConferenceById = new HashMap<>();
198    public final List<ComponentName> mRemoteConnectionServiceNames = new ArrayList<>();
199    public final List<IBinder> mRemoteConnectionServices = new ArrayList<>();
200
201    public ConnectionServiceFixture() throws Exception { }
202
203    @Override
204    public IConnectionService getTestDouble() {
205        return mConnectionServiceSpy;
206    }
207
208    public void sendHandleCreateConnectionComplete(String id) throws Exception {
209        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
210            a.handleCreateConnectionComplete(
211                    id,
212                    mConnectionById.get(id).request,
213                    parcelable(mConnectionById.get(id)));
214        }
215    }
216
217    public void sendSetActive(String id) throws Exception {
218        mConnectionById.get(id).state = Connection.STATE_ACTIVE;
219        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
220            a.setActive(id);
221        }
222    }
223
224    public void sendSetRinging(String id) throws Exception {
225        mConnectionById.get(id).state = Connection.STATE_RINGING;
226        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
227            a.setRinging(id);
228        }
229    }
230
231    public void sendSetDialing(String id) throws Exception {
232        mConnectionById.get(id).state = Connection.STATE_DIALING;
233        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
234            a.setDialing(id);
235        }
236    }
237
238    public void sendSetDisconnected(String id, int disconnectCause) throws Exception {
239        mConnectionById.get(id).state = Connection.STATE_DISCONNECTED;
240        mConnectionById.get(id).disconnectCause = new DisconnectCause(disconnectCause);
241        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
242            a.setDisconnected(id, mConnectionById.get(id).disconnectCause);
243        }
244    }
245
246    public void sendSetOnHold(String id) throws Exception {
247        mConnectionById.get(id).state = Connection.STATE_HOLDING;
248        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
249            a.setOnHold(id);
250        }
251    }
252
253    public void sendSetRingbackRequested(String id) throws Exception {
254        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
255            a.setRingbackRequested(id, mConnectionById.get(id).ringing);
256        }
257    }
258
259    public void sendSetConnectionCapabilities(String id) throws Exception {
260        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
261            a.setConnectionCapabilities(id, mConnectionById.get(id).capabilities);
262        }
263    }
264
265    public void sendSetIsConferenced(String id) throws Exception {
266        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
267            a.setIsConferenced(id, mConnectionById.get(id).conferenceId);
268        }
269    }
270
271    public void sendAddConferenceCall(String id) throws Exception {
272        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
273            a.addConferenceCall(id, parcelable(mConferenceById.get(id)));
274        }
275    }
276
277    public void sendRemoveCall(String id) throws Exception {
278        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
279            a.removeCall(id);
280        }
281    }
282
283    public void sendOnPostDialWait(String id, String remaining) throws Exception {
284        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
285            a.onPostDialWait(id, remaining);
286        }
287    }
288
289    public void sendOnPostDialChar(String id, char nextChar) throws Exception {
290        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
291            a.onPostDialChar(id, nextChar);
292        }
293    }
294
295    public void sendQueryRemoteConnectionServices() throws Exception {
296        mRemoteConnectionServices.clear();
297        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
298            a.queryRemoteConnectionServices(new RemoteServiceCallback.Stub() {
299                @Override
300                public void onError() throws RemoteException {
301                    throw new RuntimeException();
302                }
303
304                @Override
305                public void onResult(
306                        List<ComponentName> names,
307                        List<IBinder> services)
308                        throws RemoteException {
309                    TestCase.assertEquals(names.size(), services.size());
310                    mRemoteConnectionServiceNames.addAll(names);
311                    mRemoteConnectionServices.addAll(services);
312                }
313
314                @Override
315                public IBinder asBinder() {
316                    return this;
317                }
318            });
319        }
320    }
321
322    public void sendSetVideoProvider(String id) throws Exception {
323        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
324            a.setVideoProvider(id, mConnectionById.get(id).videoProvider);
325        }
326    }
327
328    public void sendSetVideoState(String id) throws Exception {
329        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
330            a.setVideoState(id, mConnectionById.get(id).videoState);
331        }
332    }
333
334    public void sendSetIsVoipAudioMode(String id) throws Exception {
335        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
336            a.setIsVoipAudioMode(id, mConnectionById.get(id).isVoipAudioMode);
337        }
338    }
339
340    public void sendSetStatusHints(String id) throws Exception {
341        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
342            a.setStatusHints(id, mConnectionById.get(id).statusHints);
343        }
344    }
345
346    public void sendSetAddress(String id) throws Exception {
347        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
348            a.setAddress(
349                    id,
350                    mConnectionById.get(id).request.getAddress(),
351                    mConnectionById.get(id).addressPresentation);
352        }
353    }
354
355    public void sendSetCallerDisplayName(String id) throws Exception {
356        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
357            a.setCallerDisplayName(
358                    id,
359                    mConnectionById.get(id).callerDisplayName,
360                    mConnectionById.get(id).callerDisplayNamePresentation);
361        }
362    }
363
364    public void sendSetConferenceableConnections(String id) throws Exception {
365        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
366            a.setConferenceableConnections(id, mConnectionById.get(id).conferenceableConnectionIds);
367        }
368    }
369
370    public void sendAddExistingConnection(String id) throws Exception {
371        for (IConnectionServiceAdapter a : mConnectionServiceAdapters) {
372            a.addExistingConnection(id, parcelable(mConnectionById.get(id)));
373        }
374    }
375
376    private ParcelableConference parcelable(ConferenceInfo c) {
377        return new ParcelableConference(
378                c.phoneAccount,
379                c.state,
380                c.capabilities,
381                c.connectionIds,
382                c.videoProvider,
383                c.videoState,
384                c.connectTimeMillis,
385                c.statusHints,
386                c.extras);
387    }
388
389    private ParcelableConnection parcelable(ConnectionInfo c) {
390        return new ParcelableConnection(
391                c.request.getAccountHandle(),
392                c.state,
393                c.capabilities,
394                c.request.getAddress(),
395                c.addressPresentation,
396                c.callerDisplayName,
397                c.callerDisplayNamePresentation,
398                c.videoProvider,
399                c.videoState,
400                false, /* ringback requested */
401                false, /* voip audio mode */
402                0, /* Connect Time for conf call on this connection */
403                c.statusHints,
404                c.disconnectCause,
405                c.conferenceableConnectionIds,
406                c.extras);
407    }
408}
409