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
129        private final RemoteConnection mRemote;
130        private final boolean mIsIncoming;
131
132        TestManagedConnection(RemoteConnection remote, boolean isIncoming) {
133            mRemote = remote;
134            mIsIncoming = isIncoming;
135            mRemote.registerCallback(mRemoteCallback);
136            setState(mRemote.getState());
137            setVideoState(mRemote.getVideoState());
138        }
139
140        @Override
141        public void onAbort() {
142            mRemote.abort();
143        }
144
145        /** ${inheritDoc} */
146        @Override
147        public void onAnswer(int videoState) {
148            mRemote.answer(videoState);
149        }
150
151        /** ${inheritDoc} */
152        @Override
153        public void onDisconnect() {
154            mRemote.disconnect();
155        }
156
157        @Override
158        public void onPlayDtmfTone(char c) {
159            mRemote.playDtmfTone(c);
160        }
161
162        /** ${inheritDoc} */
163        @Override
164        public void onHold() {
165            mRemote.hold();
166        }
167
168        /** ${inheritDoc} */
169        @Override
170        public void onReject() {
171            mRemote.reject();
172        }
173
174        /** ${inheritDoc} */
175        @Override
176        public void onUnhold() {
177            mRemote.unhold();
178        }
179
180        @Override
181        public void onCallAudioStateChanged(CallAudioState state) {
182            mRemote.setCallAudioState(state);
183        }
184
185        private void setState(int state) {
186            log("setState: " + state);
187            switch (state) {
188                case STATE_ACTIVE:
189                    setActive();
190                    break;
191                case STATE_HOLDING:
192                    setOnHold();
193                    break;
194                case STATE_DIALING:
195                    setDialing();
196                    break;
197                case STATE_RINGING:
198                    setRinging();
199                    break;
200            }
201        }
202    }
203
204    public final class TestManagedConference extends Conference {
205        private final RemoteConference.Callback mRemoteCallback = new RemoteConference.Callback() {
206            @Override
207            public void onStateChanged(RemoteConference conference, int oldState, int newState) {
208                switch (newState) {
209                    case Connection.STATE_DISCONNECTED:
210                        // See onDisconnected below
211                        break;
212                    case Connection.STATE_HOLDING:
213                        setOnHold();
214                        break;
215                    case Connection.STATE_ACTIVE:
216                        setActive();
217                        break;
218                    default:
219                        log("unrecognized state for Conference: " + newState);
220                        break;
221                }
222            }
223
224            @Override
225            public void onDisconnected(RemoteConference conference,
226                    DisconnectCause disconnectCause) {
227                setDisconnected(disconnectCause);
228            }
229
230            @Override
231            public void onConnectionAdded(
232                    RemoteConference conference,
233                    RemoteConnection connection) {
234                TestManagedConnection c = mManagedConnectionByRemote.get(connection);
235                if (c == null) {
236                    log("onConnectionAdded cannot find remote connection: " + connection);
237                } else {
238                    addConnection(c);
239                }
240            }
241
242            @Override
243            public void onConnectionRemoved(
244                    RemoteConference conference,
245                    RemoteConnection connection) {
246                TestManagedConnection c = mManagedConnectionByRemote.get(connection);
247                if (c == null) {
248                    log("onConnectionRemoved cannot find remote connection: " + connection);
249                } else {
250                    removeConnection(c);
251                }
252            }
253
254            @Override
255            public void onConnectionCapabilitiesChanged(RemoteConference conference,
256                    int connectionCapabilities) {
257                setConnectionCapabilities(connectionCapabilities);
258            }
259
260            @Override
261            public void onConnectionPropertiesChanged(RemoteConference conference,
262                    int connectionProperties) {
263                setConnectionProperties(connectionProperties);
264            }
265
266            @Override
267            public void onDestroyed(RemoteConference conference) {
268                destroy();
269                mRemote.unregisterCallback(mRemoteCallback);
270                mManagedConferenceByRemote.remove(mRemote);
271            }
272
273        };
274
275        @Override
276        public void onPlayDtmfTone(char c) {
277            mRemote.playDtmfTone(c);
278        };
279
280        @Override
281        public void onStopDtmfTone() {
282            mRemote.stopDtmfTone();
283        };
284
285        private final RemoteConference mRemote;
286
287        public TestManagedConference(RemoteConference remote) {
288            super(null);
289            mRemote = remote;
290            remote.registerCallback(mRemoteCallback);
291            setActive();
292            for (RemoteConnection r : remote.getConnections()) {
293                TestManagedConnection c = mManagedConnectionByRemote.get(r);
294                if (c != null) {
295                    addConnection(c);
296                }
297            }
298        }
299    }
300
301    static void log(String msg) {
302        Log.w("telecomtestcs", "[TestConnectionManager] " + msg);
303    }
304
305    private final Map<RemoteConference, TestManagedConference> mManagedConferenceByRemote
306            = new HashMap<>();
307    private final Map<RemoteConnection, TestManagedConnection> mManagedConnectionByRemote
308            = new HashMap<>();
309
310    @Override
311    public Connection onCreateOutgoingConnection(
312            PhoneAccountHandle connectionManagerAccount,
313            final ConnectionRequest request) {
314        return makeConnection(request, false);
315    }
316
317    @Override
318    public Connection onCreateIncomingConnection(
319            PhoneAccountHandle connectionManagerAccount,
320            final ConnectionRequest request) {
321        return makeConnection(request, true);
322    }
323
324    @Override
325    public void onConference(Connection a, Connection b) {
326        conferenceRemoteConnections(
327                ((TestManagedConnection) a).mRemote,
328                ((TestManagedConnection) b).mRemote);
329    }
330
331    @Override
332    public void onRemoteConferenceAdded(RemoteConference remoteConference) {
333        addConference(new TestManagedConference(remoteConference));
334    }
335
336    Map<RemoteConnection, TestManagedConnection> getManagedConnectionByRemote() {
337        return mManagedConnectionByRemote;
338    }
339
340    private Connection makeConnection(ConnectionRequest request, boolean incoming) {
341        RemoteConnection remote = incoming
342                ? createRemoteIncomingConnection(request.getAccountHandle(), request)
343                : createRemoteOutgoingConnection(request.getAccountHandle(), request);
344        TestManagedConnection local = new TestManagedConnection(remote, false);
345        mManagedConnectionByRemote.put(remote, local);
346        return local;
347    }
348}
349