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.telecom.Conference;
23 import android.telecom.Connection;
24 import android.telecom.ConnectionRequest;
25 import android.telecom.ConnectionService;
26 import android.telecom.PhoneAccountHandle;
27 import android.telecom.RemoteConference;
28 import android.telecom.RemoteConnection;
29 import android.util.Log;
30 
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.concurrent.CountDownLatch;
34 
35 /**
36  * This is the official ConnectionService for Telecom's CTS App. Since telecom requires that a
37  * CS be registered in the AndroidManifest.xml file, we have to have a single implementation
38  * of a CS and this is it. To test specific CS behavior, tests will implement their own CS and
39  * tell CtsConnectionService to forward any method invocations to that test's implementation.
40  * This is set up using {@link #setUp} and should be cleaned up before the end of the test using
41  * {@link #tearDown}.
42  *
43  * sConnectionService: Contains the connection service object provided by the current test in
44  *                     progress. We use this object to forward any communication received from the
45  *                     Telecom framework to the test connection service.
46  * sTelecomConnectionService: Contains the connection service object registered to the Telecom
47  *                            framework. We use this object to forward any communication from the
48  *                            test connection service to the Telecom framework. After Telecom
49  *                            binds to CtsConnectionService, this is set to be the instance of
50  *                            CtsConnectionService created by the framework after Telecom binds.
51  */
52 public class CtsConnectionService extends ConnectionService {
53     private static String LOG_TAG = "CtsConnectionService";
54     // This is the connection service implemented by the test
55     private static ConnectionService sConnectionService;
56     // This is the connection service registered with Telecom
57     private static ConnectionService sTelecomConnectionService;
58     private static boolean sIsBound = false;
59     private static CountDownLatch sServiceUnBoundLatch = new CountDownLatch(1);
60 
CtsConnectionService()61     public CtsConnectionService() throws Exception {
62         super();
63         sTelecomConnectionService = this;
64         sIsBound = true;
65     }
66 
67     private static Object sLock = new Object();
68 
setUp(ConnectionService connectionService)69     public static void setUp(ConnectionService connectionService) throws Exception {
70         synchronized(sLock) {
71             if (sConnectionService != null) {
72                 throw new Exception("Mock ConnectionService exists.  Failed to call tearDown().");
73             }
74             sConnectionService = connectionService;
75         }
76     }
77 
tearDown()78     public static void tearDown() {
79         synchronized(sLock) {
80             sTelecomConnectionService = null;
81             sConnectionService = null;
82         }
83     }
84 
85     @Override
onCreateOutgoingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)86     public Connection onCreateOutgoingConnection(PhoneAccountHandle connectionManagerPhoneAccount,
87             ConnectionRequest request) {
88         synchronized(sLock) {
89             if (sConnectionService != null) {
90                 return sConnectionService.onCreateOutgoingConnection(
91                         connectionManagerPhoneAccount, request);
92             } else {
93                 return null;
94             }
95         }
96     }
97 
98     @Override
onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)99     public Connection onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount,
100             ConnectionRequest request) {
101         synchronized(sLock) {
102             if (sConnectionService != null) {
103                 return sConnectionService.onCreateIncomingConnection(
104                         connectionManagerPhoneAccount, request);
105             } else {
106                 return null;
107             }
108         }
109     }
110 
111     @Override
onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)112     public void onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount,
113             ConnectionRequest request) {
114         if (sConnectionService != null) {
115             sConnectionService.onCreateIncomingConnectionFailed(connectionManagerPhoneAccount,
116                     request);
117         }
118     }
119 
120     @Override
onCreateOutgoingConference(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)121     public Conference onCreateOutgoingConference(PhoneAccountHandle connectionManagerPhoneAccount,
122             ConnectionRequest request) {
123         synchronized (sLock) {
124             if (sConnectionService != null) {
125                 return sConnectionService.onCreateOutgoingConference(connectionManagerPhoneAccount,
126                         request);
127             } else {
128                 return null;
129             }
130         }
131     }
132 
133     @Override
onCreateOutgoingConferenceFailed(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)134     public void onCreateOutgoingConferenceFailed(PhoneAccountHandle connectionManagerPhoneAccount,
135             ConnectionRequest request) {
136         synchronized (sLock) {
137             if (sConnectionService != null) {
138                 sConnectionService.onCreateOutgoingConferenceFailed(connectionManagerPhoneAccount,
139                         request);
140             }
141         }
142     }
143 
144     @Override
onCreateIncomingConference(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)145     public Conference onCreateIncomingConference(PhoneAccountHandle connectionManagerPhoneAccount,
146             ConnectionRequest request) {
147         synchronized (sLock) {
148             if (sConnectionService != null) {
149                 return sConnectionService.onCreateIncomingConference(connectionManagerPhoneAccount,
150                         request);
151             } else {
152                 return null;
153             }
154         }
155     }
156 
157     @Override
onCreateIncomingConferenceFailed(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)158     public void onCreateIncomingConferenceFailed(PhoneAccountHandle connectionManagerPhoneAccount,
159             ConnectionRequest request) {
160         synchronized (sLock) {
161             if (sConnectionService != null) {
162                 sConnectionService.onCreateIncomingConferenceFailed(connectionManagerPhoneAccount,
163                         request);
164             }
165         }
166     }
167 
168     @Override
onConference(Connection connection1, Connection connection2)169     public void onConference(Connection connection1, Connection connection2) {
170         synchronized(sLock) {
171             if (sConnectionService != null) {
172                 sConnectionService.onConference(connection1, connection2);
173             }
174         }
175     }
176 
177     @Override
onRemoteExistingConnectionAdded(RemoteConnection connection)178     public void onRemoteExistingConnectionAdded(RemoteConnection connection) {
179         synchronized(sLock) {
180             if (sConnectionService != null) {
181                 sConnectionService.onRemoteExistingConnectionAdded(connection);
182             }
183         }
184     }
185 
addConferenceToTelecom(Conference conference)186     public static void addConferenceToTelecom(Conference conference) {
187         synchronized(sLock) {
188             sTelecomConnectionService.addConference(conference);
189         }
190     }
191 
addExistingConnectionToTelecom( PhoneAccountHandle phoneAccountHandle, Connection connection)192     public static void addExistingConnectionToTelecom(
193             PhoneAccountHandle phoneAccountHandle, Connection connection) {
194         synchronized(sLock) {
195             sTelecomConnectionService.addExistingConnection(phoneAccountHandle, connection);
196         }
197     }
198 
getAllConnectionsFromTelecom()199     public static Collection<Connection> getAllConnectionsFromTelecom() {
200         synchronized(sLock) {
201             if (sTelecomConnectionService == null) {
202                 return Collections.EMPTY_LIST;
203             }
204             return sTelecomConnectionService.getAllConnections();
205         }
206     }
207 
createRemoteOutgoingConnectionToTelecom( PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)208     public static RemoteConnection createRemoteOutgoingConnectionToTelecom(
209             PhoneAccountHandle connectionManagerPhoneAccount,
210             ConnectionRequest request) {
211         synchronized(sLock) {
212             return sTelecomConnectionService.createRemoteOutgoingConnection(
213                     connectionManagerPhoneAccount, request);
214         }
215     }
216 
createRemoteIncomingConnectionToTelecom( PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)217     public static RemoteConnection createRemoteIncomingConnectionToTelecom(
218             PhoneAccountHandle connectionManagerPhoneAccount,
219             ConnectionRequest request) {
220         synchronized(sLock) {
221             return sTelecomConnectionService.createRemoteIncomingConnection(
222                     connectionManagerPhoneAccount, request);
223         }
224     }
225 
226     @Override
onRemoteConferenceAdded(RemoteConference conference)227     public void onRemoteConferenceAdded(RemoteConference conference) {
228         synchronized(sLock) {
229             if (sConnectionService != null) {
230                 sConnectionService.onRemoteConferenceAdded(conference);
231             }
232         }
233     }
234 
235     @Override
onConnectionServiceFocusGained()236     public void onConnectionServiceFocusGained() {
237         synchronized (sLock) {
238             if (sConnectionService != null) {
239                 sConnectionService.onConnectionServiceFocusGained();
240             }
241         }
242     }
243 
244     @Override
onConnectionServiceFocusLost()245     public void onConnectionServiceFocusLost() {
246         synchronized (sLock) {
247             if (sConnectionService != null) {
248                 sConnectionService.onConnectionServiceFocusLost();
249             }
250         }
251     }
252 
253     @Override
onUnbind(Intent intent)254     public boolean onUnbind(Intent intent) {
255         Log.i(LOG_TAG, "Service has been unbound");
256         sServiceUnBoundLatch.countDown();
257         sIsBound = false;
258         sConnectionService = null;
259         return super.onUnbind(intent);
260     }
261 
isServiceRegisteredToTelecom()262     public static boolean isServiceRegisteredToTelecom() {
263         return sTelecomConnectionService != null;
264     }
265 
isBound()266     public static boolean isBound() {
267         return sIsBound;
268     }
269 
waitForUnBinding()270     public static boolean waitForUnBinding() {
271         return TestUtils.waitForLatchCountDown(sServiceUnBoundLatch);
272     }
273 }
274