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 android.telecom.cts.TestUtils.*; 20 21 import static org.hamcrest.CoreMatchers.not; 22 import static org.hamcrest.CoreMatchers.equalTo; 23 import static org.junit.Assert.assertThat; 24 25 import android.content.ComponentName; 26 import android.telecom.Connection; 27 import android.telecom.PhoneAccount; 28 import android.telecom.PhoneAccountHandle; 29 import android.telecom.RemoteConference; 30 import android.telecom.RemoteConnection; 31 import android.text.TextUtils; 32 import android.util.Log; 33 34 import java.util.ArrayList; 35 import java.util.List; 36 import java.util.concurrent.TimeUnit; 37 38 /** 39 * Base class for Telecom CTS tests that require a {@link CtsConnectionService} and 40 * {@link CtsRemoteConnectionService} to verify Telecom functionality. This class 41 * extends from the {@link BaseTelecomTestWithMockServices} and should be extended 42 * for all RemoteConnection/RemoteConferencTest. 43 */ 44 public class BaseRemoteTelecomTest extends BaseTelecomTestWithMockServices { 45 46 public static final PhoneAccountHandle TEST_REMOTE_PHONE_ACCOUNT_HANDLE = 47 new PhoneAccountHandle(new ComponentName(PACKAGE, REMOTE_COMPONENT), REMOTE_ACCOUNT_ID); 48 public static final String TEST_REMOTE_PHONE_ACCOUNT_ADDRESS = "tel:666-TEST"; 49 50 MockConnectionService remoteConnectionService = null; 51 52 @Override tearDown()53 protected void tearDown() throws Exception { 54 if (mShouldTestTelecom) { 55 tearDownRemoteConnectionService(TEST_REMOTE_PHONE_ACCOUNT_HANDLE); 56 } 57 super.tearDown(); 58 } 59 setupConnectionServices(MockConnectionService connectionService, MockConnectionService remoteConnectionService, int flags)60 protected void setupConnectionServices(MockConnectionService connectionService, 61 MockConnectionService remoteConnectionService, int flags) throws Exception { 62 // Setup the primary connection service first 63 setupConnectionService(connectionService, flags); 64 setupRemoteConnectionService(remoteConnectionService, flags); 65 } 66 setupRemoteConnectionService(MockConnectionService remoteConnectionService, int flags)67 protected void setupRemoteConnectionService(MockConnectionService remoteConnectionService, 68 int flags) throws Exception { 69 if (remoteConnectionService != null) { 70 this.remoteConnectionService = remoteConnectionService; 71 } else { 72 // Generate a vanilla mock connection service, if not provided. 73 this.remoteConnectionService = new MockConnectionService(); 74 } 75 CtsRemoteConnectionService.setUp(TEST_REMOTE_PHONE_ACCOUNT_HANDLE, 76 this.remoteConnectionService); 77 78 if ((flags & FLAG_REGISTER) != 0) { 79 // This needs SIM subscription, so register via adb commands to get system permission. 80 TestUtils.registerSimPhoneAccount(getInstrumentation(), 81 TEST_REMOTE_PHONE_ACCOUNT_HANDLE, 82 REMOTE_ACCOUNT_LABEL, 83 TEST_REMOTE_PHONE_ACCOUNT_ADDRESS); 84 // Wait till the adb commands have executed and account is in Telecom database. 85 assertPhoneAccountRegistered(TEST_REMOTE_PHONE_ACCOUNT_HANDLE); 86 } 87 if ((flags & FLAG_ENABLE) != 0) { 88 TestUtils.enablePhoneAccount(getInstrumentation(), TEST_REMOTE_PHONE_ACCOUNT_HANDLE); 89 // Wait till the adb commands have executed and account is enabled in Telecom database. 90 assertPhoneAccountEnabled(TEST_REMOTE_PHONE_ACCOUNT_HANDLE); 91 } 92 } 93 tearDownRemoteConnectionService(PhoneAccountHandle remoteAccountHandle)94 protected void tearDownRemoteConnectionService(PhoneAccountHandle remoteAccountHandle) 95 throws Exception { 96 assertNumConnections(this.remoteConnectionService, 0); 97 mTelecomManager.unregisterPhoneAccount(remoteAccountHandle); 98 CtsRemoteConnectionService.tearDown(); 99 //Telecom doesn't unbind the remote connection service at the end of all calls today. 100 //assertCtsRemoteConnectionServiceUnbound(); 101 this.remoteConnectionService = null; 102 } 103 verifyConnectionForOutgoingCallOnRemoteCS()104 MockConnection verifyConnectionForOutgoingCallOnRemoteCS() { 105 // Assuming only 1 connection present 106 return verifyConnectionForOutgoingCallOnRemoteCS(0); 107 } 108 verifyConnectionForOutgoingCallOnRemoteCS(int connectionIndex)109 MockConnection verifyConnectionForOutgoingCallOnRemoteCS(int connectionIndex) { 110 try { 111 if (!remoteConnectionService.lock.tryAcquire(TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS, 112 TimeUnit.MILLISECONDS)) { 113 fail("No outgoing call connection requested by Telecom"); 114 } 115 } catch (InterruptedException e) { 116 Log.i(TAG, "Test interrupted!"); 117 } 118 119 assertThat("Telecom should create outgoing connection for remote outgoing call", 120 remoteConnectionService.outgoingConnections.size(), not(equalTo(0))); 121 assertEquals("Telecom should not create incoming connections for remote outgoing calls", 122 0, remoteConnectionService.incomingConnections.size()); 123 MockConnection connection = remoteConnectionService.outgoingConnections.get(connectionIndex); 124 return connection; 125 } 126 verifyConnectionForIncomingCallOnRemoteCS()127 MockConnection verifyConnectionForIncomingCallOnRemoteCS() { 128 // Assuming only 1 connection present 129 return verifyConnectionForIncomingCallOnRemoteCS(0); 130 } 131 verifyConnectionForIncomingCallOnRemoteCS(int connectionIndex)132 MockConnection verifyConnectionForIncomingCallOnRemoteCS(int connectionIndex) { 133 try { 134 if (!remoteConnectionService.lock.tryAcquire(TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS, 135 TimeUnit.MILLISECONDS)) { 136 fail("No outgoing call connection requested by Telecom"); 137 } 138 } catch (InterruptedException e) { 139 Log.i(TAG, "Test interrupted!"); 140 } 141 142 assertThat("Telecom should create incoming connections for remote incoming calls", 143 remoteConnectionService.incomingConnections.size(), not(equalTo(0))); 144 assertEquals("Telecom should not create outgoing connections for remote incoming calls", 145 0, remoteConnectionService.outgoingConnections.size()); 146 MockConnection connection = remoteConnectionService.incomingConnections.get(connectionIndex); 147 setAndVerifyConnectionForIncomingCall(connection); 148 return connection; 149 } 150 setAndVerifyConferenceablesForOutgoingConnectionOnRemoteCS(int connectionIndex)151 void setAndVerifyConferenceablesForOutgoingConnectionOnRemoteCS(int connectionIndex) { 152 assertEquals("Lock should have no permits!", 0, mInCallCallbacks.lock.availablePermits()); 153 /** 154 * Set the conferenceable connections on the given connection and it's remote connection 155 * counterpart. 156 */ 157 // Make all other outgoing connections as conferenceable with this remote connection. 158 MockConnection connection = remoteConnectionService.outgoingConnections.get(connectionIndex); 159 List<Connection> confConnections = 160 new ArrayList<>(remoteConnectionService.outgoingConnections.size()); 161 for (Connection c : remoteConnectionService.outgoingConnections) { 162 if (c != connection) { 163 confConnections.add(c); 164 } 165 } 166 connection.setConferenceableConnections(confConnections); 167 assertEquals(connection.getConferenceables(), confConnections); 168 } 169 verifyConferenceForOutgoingCallOnRemoteCS()170 MockConference verifyConferenceForOutgoingCallOnRemoteCS() { 171 try { 172 if (!remoteConnectionService.lock.tryAcquire(TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS, 173 TimeUnit.MILLISECONDS)) { 174 fail("No outgoing conference requested by Telecom"); 175 } 176 } catch (InterruptedException e) { 177 Log.i(TAG, "Test interrupted!"); 178 } 179 // Return the newly created conference object to the caller 180 MockConference conference = remoteConnectionService.conferences.get(0); 181 setAndVerifyConferenceForOutgoingCall(conference); 182 return conference; 183 } 184 assertRemoteConnectionState(final RemoteConnection connection, final int state)185 void assertRemoteConnectionState(final RemoteConnection connection, final int state) { 186 waitUntilConditionIsTrueOrTimeout( 187 new Condition() { 188 @Override 189 public Object expected() { 190 return state; 191 } 192 193 @Override 194 public Object actual() { 195 return connection.getState(); 196 } 197 }, 198 WAIT_FOR_STATE_CHANGE_TIMEOUT_MS, 199 "Remote Connection should be in state " + state 200 ); 201 } 202 assertRemoteConferenceState(final RemoteConference conference, final int state)203 void assertRemoteConferenceState(final RemoteConference conference, final int state) { 204 waitUntilConditionIsTrueOrTimeout( 205 new Condition() { 206 @Override 207 public Object expected() { 208 return state; 209 } 210 211 @Override 212 public Object actual() { 213 return conference.getState(); 214 } 215 }, 216 WAIT_FOR_STATE_CHANGE_TIMEOUT_MS, 217 "Remote Conference should be in state " + state 218 ); 219 } 220 assertCtsRemoteConnectionServiceUnbound()221 void assertCtsRemoteConnectionServiceUnbound() { 222 waitUntilConditionIsTrueOrTimeout( 223 new Condition() { 224 @Override 225 public Object expected(){ 226 return true; 227 } 228 229 @Override 230 public Object actual() { 231 return CtsRemoteConnectionService.isServiceUnbound(); 232 } 233 }, 234 WAIT_FOR_STATE_CHANGE_TIMEOUT_MS, 235 "CtsRemoteConnectionService not yet unbound!" 236 ); 237 } 238 } 239