1/*
2 * Copyright (C) 2013 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.testapps;
18
19import android.net.Uri;
20import android.telecom.CallAudioState;
21import android.telecom.Conference;
22import android.telecom.Connection;
23import android.telecom.ConnectionRequest;
24import android.telecom.ConnectionService;
25import android.telecom.DisconnectCause;
26import android.telecom.PhoneAccountHandle;
27import android.telecom.RemoteConference;
28import android.telecom.RemoteConnection;
29import android.telecom.StatusHints;
30import android.telecom.VideoProfile;
31import android.util.Log;
32
33import java.util.ArrayList;
34import java.util.HashMap;
35import java.util.List;
36import java.util.Map;
37
38/**
39 * Service which acts as a fake ConnectionManager if so configured.
40 * TODO(santoscordon): Rename all classes in the directory to Dummy* (e.g., DummyConnectionService).
41 */
42public class TestConnectionManager extends ConnectionService {
43    public final class TestManagedConnection extends Connection {
44        private final RemoteConnection.Callback mRemoteCallback = new RemoteConnection.Callback() {
45            @Override
46            public void onStateChanged(RemoteConnection connection, int state) {
47                setState(state);
48            }
49
50            @Override
51            public void onDisconnected(
52                    RemoteConnection connection, DisconnectCause disconnectCause) {
53                setDisconnected(disconnectCause);
54                destroy();
55            }
56
57            @Override
58            public void onRingbackRequested(RemoteConnection connection, boolean ringback) {
59                setRingbackRequested(ringback);
60            }
61
62            @Override
63            public void onConnectionCapabilitiesChanged(RemoteConnection connection,
64                    int connectionCapabilities) {
65                setConnectionCapabilities(connectionCapabilities);
66            }
67
68            @Override
69            public void onConnectionPropertiesChanged(RemoteConnection connection,
70                    int connectionProperties) {
71                setConnectionProperties(connectionProperties);
72            }
73
74            @Override
75            public void onPostDialWait(RemoteConnection connection, String remainingDigits) {
76                setPostDialWait(remainingDigits);
77            }
78
79            @Override
80            public void onVoipAudioChanged(RemoteConnection connection, boolean isVoip) {
81                setAudioModeIsVoip(isVoip);
82            }
83
84            @Override
85            public void onStatusHintsChanged(RemoteConnection connection, StatusHints statusHints) {
86                setStatusHints(statusHints);
87            }
88
89            @Override
90            public void onVideoStateChanged(RemoteConnection connection, int videoState) {
91                if (videoState == VideoProfile.STATE_BIDIRECTIONAL) {
92                    setVideoProvider(new TestManagedVideoProvider(connection.getVideoProvider()));
93                }
94                setVideoState(videoState);
95            }
96
97            @Override
98            public void onAddressChanged(
99                    RemoteConnection connection, Uri address, int presentation) {
100                setAddress(address, presentation);
101            }
102
103            @Override
104            public void onCallerDisplayNameChanged(
105                    RemoteConnection connection, String callerDisplayName, int presentation) {
106                setCallerDisplayName(callerDisplayName, presentation);
107            }
108
109            @Override
110            public void onDestroyed(RemoteConnection connection) {
111                destroy();
112                mManagedConnectionByRemote.remove(mRemote);
113            }
114
115            @Override
116            public void onConferenceableConnectionsChanged(
117                    RemoteConnection connect,
118                    List<RemoteConnection> conferenceable) {
119                List<Connection> c = new ArrayList<>();
120                for (RemoteConnection remote : conferenceable) {
121                    if (mManagedConnectionByRemote.containsKey(remote)) {
122                        c.add(mManagedConnectionByRemote.get(remote));
123                    }
124                }
125                setConferenceableConnections(c);
126            }
127
128            @Override
129            public void onRttInitiationSuccess(RemoteConnection connection) {
130                sendRttInitiationSuccess();
131            }
132
133            @Override
134            public void onRttInitiationFailure(RemoteConnection connection, int reason) {
135                sendRttInitiationFailure(reason);
136            }
137
138            @Override
139            public void onRttSessionRemotelyTerminated(RemoteConnection connection) {
140                sendRttSessionRemotelyTerminated();
141            }
142
143            @Override
144            public void onRemoteRttRequest(RemoteConnection connection) {
145                sendRemoteRttRequest();
146            }
147        };
148
149        private final RemoteConnection mRemote;
150        private final boolean mIsIncoming;
151
152        TestManagedConnection(RemoteConnection remote, boolean isIncoming) {
153            mRemote = remote;
154            mIsIncoming = isIncoming;
155            mRemote.registerCallback(mRemoteCallback);
156            setState(mRemote.getState());
157            setVideoState(mRemote.getVideoState());
158            setConnectionProperties(remote.getConnectionProperties());
159        }
160
161        @Override
162        public void onAbort() {
163            mRemote.abort();
164        }
165
166        /**
167         * ${inheritDoc}
168         */
169        @Override
170        public void onAnswer(int videoState) {
171            mRemote.answer(videoState);
172        }
173
174        /**
175         * ${inheritDoc}
176         */
177        @Override
178        public void onDisconnect() {
179            mRemote.disconnect();
180        }
181
182        @Override
183        public void onPlayDtmfTone(char c) {
184            mRemote.playDtmfTone(c);
185        }
186
187        /**
188         * ${inheritDoc}
189         */
190        @Override
191        public void onHold() {
192            mRemote.hold();
193        }
194
195        /**
196         * ${inheritDoc}
197         */
198        @Override
199        public void onReject() {
200            mRemote.reject();
201        }
202
203        /**
204         * ${inheritDoc}
205         */
206        @Override
207        public void onUnhold() {
208            mRemote.unhold();
209        }
210
211        @Override
212        public void onCallAudioStateChanged(CallAudioState state) {
213            mRemote.setCallAudioState(state);
214        }
215
216        @Override
217        public void onStartRtt(RttTextStream rttTextStream) {
218            mRemote.startRtt(rttTextStream);
219        }
220
221        @Override
222        public void onStopRtt() {
223            mRemote.stopRtt();
224        }
225
226        @Override
227        public void handleRttUpgradeResponse(RttTextStream rttTextStream) {
228            mRemote.sendRttUpgradeResponse(rttTextStream);
229        }
230
231        private void setState(int state) {
232            log("setState: " + state);
233            switch (state) {
234                case STATE_ACTIVE:
235                    setActive();
236                    break;
237                case STATE_HOLDING:
238                    setOnHold();
239                    break;
240                case STATE_DIALING:
241                    setDialing();
242                    break;
243                case STATE_RINGING:
244                    setRinging();
245                    break;
246            }
247        }
248    }
249    public final class TestManagedConference extends Conference {
250        private final RemoteConference.Callback mRemoteCallback = new RemoteConference.Callback() {
251            @Override
252            public void onStateChanged(RemoteConference conference, int oldState, int newState) {
253                switch (newState) {
254                    case Connection.STATE_DISCONNECTED:
255                        // See onDisconnected below
256                        break;
257                    case Connection.STATE_HOLDING:
258                        setOnHold();
259                        break;
260                    case Connection.STATE_ACTIVE:
261                        setActive();
262                        break;
263                    default:
264                        log("unrecognized state for Conference: " + newState);
265                        break;
266                }
267            }
268
269            @Override
270            public void onDisconnected(RemoteConference conference,
271                    DisconnectCause disconnectCause) {
272                setDisconnected(disconnectCause);
273            }
274
275            @Override
276            public void onConnectionAdded(
277                    RemoteConference conference,
278                    RemoteConnection connection) {
279                TestManagedConnection c = mManagedConnectionByRemote.get(connection);
280                if (c == null) {
281                    log("onConnectionAdded cannot find remote connection: " + connection);
282                } else {
283                    addConnection(c);
284                }
285            }
286
287            @Override
288            public void onConnectionRemoved(
289                    RemoteConference conference,
290                    RemoteConnection connection) {
291                TestManagedConnection c = mManagedConnectionByRemote.get(connection);
292                if (c == null) {
293                    log("onConnectionRemoved cannot find remote connection: " + connection);
294                } else {
295                    removeConnection(c);
296                }
297            }
298
299            @Override
300            public void onConnectionCapabilitiesChanged(RemoteConference conference,
301                    int connectionCapabilities) {
302                setConnectionCapabilities(connectionCapabilities);
303            }
304
305            @Override
306            public void onConnectionPropertiesChanged(RemoteConference conference,
307                    int connectionProperties) {
308                setConnectionProperties(connectionProperties);
309            }
310
311            @Override
312            public void onDestroyed(RemoteConference conference) {
313                destroy();
314                mRemote.unregisterCallback(mRemoteCallback);
315                mManagedConferenceByRemote.remove(mRemote);
316            }
317
318        };
319
320        @Override
321        public void onPlayDtmfTone(char c) {
322            mRemote.playDtmfTone(c);
323        };
324
325        @Override
326        public void onStopDtmfTone() {
327            mRemote.stopDtmfTone();
328        };
329
330        private final RemoteConference mRemote;
331
332        public TestManagedConference(RemoteConference remote) {
333            super(null);
334            mRemote = remote;
335            remote.registerCallback(mRemoteCallback);
336            setActive();
337            for (RemoteConnection r : remote.getConnections()) {
338                TestManagedConnection c = mManagedConnectionByRemote.get(r);
339                if (c != null) {
340                    addConnection(c);
341                }
342            }
343        }
344    }
345
346    static void log(String msg) {
347        Log.w("telecomtestcs", "[TestConnectionManager] " + msg);
348    }
349
350    private final Map<RemoteConference, TestManagedConference> mManagedConferenceByRemote
351            = new HashMap<>();
352    private final Map<RemoteConnection, TestManagedConnection> mManagedConnectionByRemote
353            = new HashMap<>();
354
355    @Override
356    public Connection onCreateOutgoingConnection(
357            PhoneAccountHandle connectionManagerAccount,
358            final ConnectionRequest request) {
359        return makeConnection(request, false);
360    }
361
362    @Override
363    public Connection onCreateIncomingConnection(
364            PhoneAccountHandle connectionManagerAccount,
365            final ConnectionRequest request) {
366        return makeConnection(request, true);
367    }
368
369    @Override
370    public void onConference(Connection a, Connection b) {
371        conferenceRemoteConnections(
372                ((TestManagedConnection) a).mRemote,
373                ((TestManagedConnection) b).mRemote);
374    }
375
376    @Override
377    public void onRemoteConferenceAdded(RemoteConference remoteConference) {
378        addConference(new TestManagedConference(remoteConference));
379    }
380
381    Map<RemoteConnection, TestManagedConnection> getManagedConnectionByRemote() {
382        return mManagedConnectionByRemote;
383    }
384
385    private Connection makeConnection(ConnectionRequest request, boolean incoming) {
386        RemoteConnection remote = incoming
387                ? createRemoteIncomingConnection(request.getAccountHandle(), request)
388                : createRemoteOutgoingConnection(request.getAccountHandle(), request);
389        TestManagedConnection local = new TestManagedConnection(remote, false);
390        mManagedConnectionByRemote.put(remote, local);
391        return local;
392    }
393}
394