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 
17 package com.android.server.telecom.testapps;
18 
19 import android.net.Uri;
20 import android.telecom.CallAudioState;
21 import android.telecom.Conference;
22 import android.telecom.Connection;
23 import android.telecom.ConnectionRequest;
24 import android.telecom.ConnectionService;
25 import android.telecom.DisconnectCause;
26 import android.telecom.PhoneAccountHandle;
27 import android.telecom.RemoteConference;
28 import android.telecom.RemoteConnection;
29 import android.telecom.StatusHints;
30 import android.telecom.VideoProfile;
31 import android.util.Log;
32 
33 import java.util.ArrayList;
34 import java.util.HashMap;
35 import java.util.List;
36 import 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  */
42 public 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 
TestManagedConnection(RemoteConnection remote, boolean isIncoming)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
onAbort()141         public void onAbort() {
142             mRemote.abort();
143         }
144 
145         /** ${inheritDoc} */
146         @Override
onAnswer(int videoState)147         public void onAnswer(int videoState) {
148             mRemote.answer(videoState);
149         }
150 
151         /** ${inheritDoc} */
152         @Override
onDisconnect()153         public void onDisconnect() {
154             mRemote.disconnect();
155         }
156 
157         @Override
onPlayDtmfTone(char c)158         public void onPlayDtmfTone(char c) {
159             mRemote.playDtmfTone(c);
160         }
161 
162         /** ${inheritDoc} */
163         @Override
onHold()164         public void onHold() {
165             mRemote.hold();
166         }
167 
168         /** ${inheritDoc} */
169         @Override
onReject()170         public void onReject() {
171             mRemote.reject();
172         }
173 
174         /** ${inheritDoc} */
175         @Override
onUnhold()176         public void onUnhold() {
177             mRemote.unhold();
178         }
179 
180         @Override
onCallAudioStateChanged(CallAudioState state)181         public void onCallAudioStateChanged(CallAudioState state) {
182             mRemote.setCallAudioState(state);
183         }
184 
setState(int state)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
onPlayDtmfTone(char c)276         public void onPlayDtmfTone(char c) {
277             mRemote.playDtmfTone(c);
278         };
279 
280         @Override
onStopDtmfTone()281         public void onStopDtmfTone() {
282             mRemote.stopDtmfTone();
283         };
284 
285         private final RemoteConference mRemote;
286 
TestManagedConference(RemoteConference remote)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 
log(String msg)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
onCreateOutgoingConnection( PhoneAccountHandle connectionManagerAccount, final ConnectionRequest request)311     public Connection onCreateOutgoingConnection(
312             PhoneAccountHandle connectionManagerAccount,
313             final ConnectionRequest request) {
314         return makeConnection(request, false);
315     }
316 
317     @Override
onCreateIncomingConnection( PhoneAccountHandle connectionManagerAccount, final ConnectionRequest request)318     public Connection onCreateIncomingConnection(
319             PhoneAccountHandle connectionManagerAccount,
320             final ConnectionRequest request) {
321         return makeConnection(request, true);
322     }
323 
324     @Override
onConference(Connection a, Connection b)325     public void onConference(Connection a, Connection b) {
326         conferenceRemoteConnections(
327                 ((TestManagedConnection) a).mRemote,
328                 ((TestManagedConnection) b).mRemote);
329     }
330 
331     @Override
onRemoteConferenceAdded(RemoteConference remoteConference)332     public void onRemoteConferenceAdded(RemoteConference remoteConference) {
333         addConference(new TestManagedConference(remoteConference));
334     }
335 
getManagedConnectionByRemote()336     Map<RemoteConnection, TestManagedConnection> getManagedConnectionByRemote() {
337         return mManagedConnectionByRemote;
338     }
339 
makeConnection(ConnectionRequest request, boolean incoming)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