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