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 
17 package android.telecom.cts;
18 
19 import static org.junit.Assert.assertTrue;
20 
21 import android.content.Intent;
22 import android.os.IBinder;
23 import android.telecom.Conference;
24 import android.telecom.Connection;
25 import android.telecom.ConnectionRequest;
26 import android.telecom.ConnectionService;
27 import android.telecom.PhoneAccountHandle;
28 import android.telecom.RemoteConference;
29 import android.telecom.RemoteConnection;
30 import android.util.Log;
31 
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.concurrent.CountDownLatch;
35 
36 /**
37  * This is the official ConnectionService for Telecom's CTS App. Since telecom requires that a
38  * CS be registered in the AndroidManifest.xml file, we have to have a single implementation
39  * of a CS and this is it. To test specific CS behavior, tests will implement their own CS and
40  * tell CtsConnectionService to forward any method invocations to that test's implementation.
41  * This is set up using {@link #setUp} and should be cleaned up before the end of the test using
42  * {@link #tearDown}.
43  *
44  * sConnectionService: Contains the connection service object provided by the current test in
45  *                     progress. We use this object to forward any communication received from the
46  *                     Telecom framework to the test connection service.
47  * sTelecomConnectionService: Contains the connection service object registered to the Telecom
48  *                            framework. We use this object to forward any communication from the
49  *                            test connection service to the Telecom framework. After Telecom
50  *                            binds to CtsConnectionService, this is set to be the instance of
51  *                            CtsConnectionService created by the framework after Telecom binds.
52  */
53 public class CtsConnectionService extends ConnectionService {
54     private static String LOG_TAG = "CtsConnectionService";
55     // This is the connection service implemented by the test
56     private static ConnectionService sConnectionService;
57     // This is the connection service registered with Telecom
58     private static ConnectionService sTelecomConnectionService;
59     private static boolean sIsBound = false;
60     private static CountDownLatch sServiceUnBoundLatch = new CountDownLatch(1);
61 
62     @Override
onBindClient(Intent intent)63     public void onBindClient(Intent intent) {
64         sTelecomConnectionService = this;
65         Log.i("TelecomCTS", "CS bound");
66         sIsBound = true;
67     }
68 
69     private static Object sLock = new Object();
70 
setUp(ConnectionService connectionService)71     public static void setUp(ConnectionService connectionService) throws Exception {
72         synchronized(sLock) {
73             if (sConnectionService != null) {
74                 throw new Exception("Mock ConnectionService exists.  Failed to call setUp().");
75             }
76             sConnectionService = connectionService;
77         }
78     }
79 
tearDown()80     public static void tearDown() {
81         synchronized(sLock) {
82             sConnectionService = null;
83         }
84     }
85 
86     @Override
onCreateOutgoingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)87     public Connection onCreateOutgoingConnection(PhoneAccountHandle connectionManagerPhoneAccount,
88             ConnectionRequest request) {
89         synchronized(sLock) {
90             if (sConnectionService != null) {
91                 return sConnectionService.onCreateOutgoingConnection(
92                         connectionManagerPhoneAccount, request);
93             } else {
94                 Log.e(LOG_TAG,
95                         "Tried to create outgoing connection when sConnectionService null!");
96                 return null;
97             }
98         }
99     }
100 
101     @Override
onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)102     public Connection onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount,
103             ConnectionRequest request) {
104         synchronized(sLock) {
105             if (sConnectionService != null) {
106                 return sConnectionService.onCreateIncomingConnection(
107                         connectionManagerPhoneAccount, request);
108             } else {
109                 Log.e(LOG_TAG,
110                         "Tried to create incoming connection when sConnectionService null!");
111                 return null;
112             }
113         }
114     }
115 
116     @Override
onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)117     public void onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount,
118             ConnectionRequest request) {
119         if (sConnectionService != null) {
120             sConnectionService.onCreateIncomingConnectionFailed(connectionManagerPhoneAccount,
121                     request);
122         } else {
123             Log.e(LOG_TAG,
124                     "onCreateIncomingConnectionFailed called when sConnectionService null!");
125         }
126     }
127 
128     @Override
onCreateOutgoingConference(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)129     public Conference onCreateOutgoingConference(PhoneAccountHandle connectionManagerPhoneAccount,
130             ConnectionRequest request) {
131         synchronized (sLock) {
132             if (sConnectionService != null) {
133                 return sConnectionService.onCreateOutgoingConference(connectionManagerPhoneAccount,
134                         request);
135             } else {
136                 Log.e(LOG_TAG,
137                         "onCreateOutgoingConference called when sConnectionService null!");
138                 return null;
139             }
140         }
141     }
142 
143     @Override
onCreateOutgoingConferenceFailed(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)144     public void onCreateOutgoingConferenceFailed(PhoneAccountHandle connectionManagerPhoneAccount,
145             ConnectionRequest request) {
146         synchronized (sLock) {
147             if (sConnectionService != null) {
148                 sConnectionService.onCreateOutgoingConferenceFailed(connectionManagerPhoneAccount,
149                         request);
150             } else {
151                 Log.e(LOG_TAG,
152                         "onCreateOutgoingConferenceFailed called when sConnectionService null!");
153             }
154         }
155     }
156 
157     @Override
onCreateIncomingConference(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)158     public Conference onCreateIncomingConference(PhoneAccountHandle connectionManagerPhoneAccount,
159             ConnectionRequest request) {
160         synchronized (sLock) {
161             if (sConnectionService != null) {
162                 return sConnectionService.onCreateIncomingConference(connectionManagerPhoneAccount,
163                         request);
164             } else {
165                 Log.e(LOG_TAG,
166                         "onCreateIncomingConference called when sConnectionService null!");
167                 return null;
168             }
169         }
170     }
171 
172     @Override
onCreateIncomingConferenceFailed(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)173     public void onCreateIncomingConferenceFailed(PhoneAccountHandle connectionManagerPhoneAccount,
174             ConnectionRequest request) {
175         synchronized (sLock) {
176             if (sConnectionService != null) {
177                 sConnectionService.onCreateIncomingConferenceFailed(connectionManagerPhoneAccount,
178                         request);
179             } else {
180                 Log.e(LOG_TAG,
181                         "onCreateIncomingConferenceFailed called when sConnectionService null!");
182             }
183         }
184     }
185 
186     @Override
onConference(Connection connection1, Connection connection2)187     public void onConference(Connection connection1, Connection connection2) {
188         synchronized(sLock) {
189             if (sConnectionService != null) {
190                 sConnectionService.onConference(connection1, connection2);
191             } else {
192                 Log.e(LOG_TAG,
193                         "onConference called when sConnectionService null!");
194             }
195         }
196     }
197 
198     @Override
onRemoteExistingConnectionAdded(RemoteConnection connection)199     public void onRemoteExistingConnectionAdded(RemoteConnection connection) {
200         synchronized(sLock) {
201             if (sConnectionService != null) {
202                 sConnectionService.onRemoteExistingConnectionAdded(connection);
203             } else {
204                 Log.e(LOG_TAG,
205                         "onRemoteExistingConnectionAdded called when sConnectionService null!");
206             }
207         }
208     }
209 
addConferenceToTelecom(Conference conference)210     public static void addConferenceToTelecom(Conference conference) {
211         synchronized(sLock) {
212             if (sTelecomConnectionService != null) {
213                 sTelecomConnectionService.addConference(conference);
214             } else {
215                 Log.e(LOG_TAG, "addConferenceToTelecom called when"
216                         + " sTelecomConnectionService null!");
217             }
218         }
219     }
220 
addExistingConnectionToTelecom( PhoneAccountHandle phoneAccountHandle, Connection connection)221     public static void addExistingConnectionToTelecom(
222             PhoneAccountHandle phoneAccountHandle, Connection connection) {
223         synchronized(sLock) {
224             if (sTelecomConnectionService != null) {
225                 sTelecomConnectionService.addExistingConnection(phoneAccountHandle, connection);
226             } else {
227                 Log.e(LOG_TAG, "addExistingConnectionToTelecom called when"
228                         + " sTelecomConnectionService null!");
229             }
230         }
231     }
232 
getAllConnectionsFromTelecom()233     public static Collection<Connection> getAllConnectionsFromTelecom() {
234         synchronized(sLock) {
235             if (sTelecomConnectionService == null) {
236                 return Collections.EMPTY_LIST;
237             }
238             return sTelecomConnectionService.getAllConnections();
239         }
240     }
241 
createRemoteOutgoingConnectionToTelecom( PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)242     public static RemoteConnection createRemoteOutgoingConnectionToTelecom(
243             PhoneAccountHandle connectionManagerPhoneAccount,
244             ConnectionRequest request) {
245         synchronized(sLock) {
246             if (sTelecomConnectionService != null) {
247                 return sTelecomConnectionService.createRemoteOutgoingConnection(
248                         connectionManagerPhoneAccount, request);
249             } else {
250                 Log.e(LOG_TAG, "createRemoteOutgoingConnectionToTelecom called when"
251                         + " sTelecomConnectionService null!");
252                 return null;
253             }
254         }
255     }
256 
createRemoteIncomingConnectionToTelecom( PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)257     public static RemoteConnection createRemoteIncomingConnectionToTelecom(
258             PhoneAccountHandle connectionManagerPhoneAccount,
259             ConnectionRequest request) {
260         synchronized(sLock) {
261             if (sTelecomConnectionService != null) {
262                 return sTelecomConnectionService.createRemoteIncomingConnection(
263                         connectionManagerPhoneAccount, request);
264             } else {
265                 Log.e(LOG_TAG, "createRemoteIncomingConnectionToTelecom called when"
266                         + " sTelecomConnectionService null!");
267                 return null;
268             }
269         }
270     }
271 
createRemoteIncomingConferenceToTelecom( PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)272     public static RemoteConference createRemoteIncomingConferenceToTelecom(
273             PhoneAccountHandle connectionManagerPhoneAccount,
274             ConnectionRequest request) {
275         synchronized (sLock) {
276             if (sTelecomConnectionService != null) {
277                 return sTelecomConnectionService.createRemoteIncomingConference(
278                         connectionManagerPhoneAccount, request);
279             } else {
280                 Log.e(LOG_TAG, "createRemoteIncomingConferenceToTelecom called when"
281                         + " sTelecomConnectionService null!");
282                 return null;
283             }
284         }
285     }
286 
287 
createRemoteOutgoingConferenceToTelecom( PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)288     public static RemoteConference createRemoteOutgoingConferenceToTelecom(
289             PhoneAccountHandle connectionManagerPhoneAccount,
290             ConnectionRequest request) {
291         synchronized (sLock) {
292             if (sTelecomConnectionService != null) {
293                 return sTelecomConnectionService.createRemoteOutgoingConference(
294                         connectionManagerPhoneAccount, request);
295             } else {
296                 Log.e(LOG_TAG, "createRemoteOutgoingConferenceToTelecom called when"
297                         + " sTelecomConnectionService null!");
298                 return null;
299             }
300         }
301     }
302 
303     @Override
onRemoteConferenceAdded(RemoteConference conference)304     public void onRemoteConferenceAdded(RemoteConference conference) {
305         synchronized(sLock) {
306             if (sConnectionService != null) {
307                 sConnectionService.onRemoteConferenceAdded(conference);
308             } else {
309                 Log.e(LOG_TAG,
310                         "onRemoteConferenceAdded called when sConnectionService null!");
311             }
312         }
313     }
314 
315     @Override
onConnectionServiceFocusGained()316     public void onConnectionServiceFocusGained() {
317         synchronized (sLock) {
318             if (sConnectionService != null) {
319                 sConnectionService.onConnectionServiceFocusGained();
320             } else {
321                 Log.e(LOG_TAG,
322                         "onConnectionServiceFocusGained called when sConnectionService null!");
323             }
324         }
325     }
326 
327     @Override
onConnectionServiceFocusLost()328     public void onConnectionServiceFocusLost() {
329         synchronized (sLock) {
330             if (sConnectionService != null) {
331                 sConnectionService.onConnectionServiceFocusLost();
332             } else {
333                 Log.e(LOG_TAG,
334                         "onConnectionServiceFocusLost called when sConnectionService null!");
335             }
336         }
337     }
338 
339     @Override
onUnbind(Intent intent)340     public boolean onUnbind(Intent intent) {
341         synchronized (sLock) {
342             Log.i(LOG_TAG, "Service has been unbound");
343             sIsBound = false;
344             sServiceUnBoundLatch.countDown();
345             sConnectionService = null;
346             sTelecomConnectionService = null;
347             return super.onUnbind(intent);
348         }
349     }
350 
isServiceRegisteredToTelecom()351     public static boolean isServiceRegisteredToTelecom() {
352         return sTelecomConnectionService != null;
353     }
354 
isBound()355     public static boolean isBound() {
356         return sIsBound;
357     }
358 
waitForUnBinding()359     public static boolean waitForUnBinding() {
360         return TestUtils.waitForLatchCountDown(sServiceUnBoundLatch);
361     }
362 }
363