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