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 com.android.server.telecom.tests; 18 19 import org.junit.After; 20 import org.junit.Before; 21 import org.junit.Test; 22 import org.junit.runner.RunWith; 23 import org.junit.runners.JUnit4; 24 import org.mockito.ArgumentCaptor; 25 26 import android.os.Process; 27 import android.os.RemoteException; 28 import android.telecom.CallAudioState; 29 import android.telecom.DisconnectCause; 30 import android.telecom.VideoProfile; 31 import android.test.suitebuilder.annotation.LargeTest; 32 import android.test.suitebuilder.annotation.MediumTest; 33 34 import com.android.server.telecom.CallAudioModeStateMachine; 35 import com.android.server.telecom.CallAudioRouteStateMachine; 36 37 import java.util.List; 38 39 import static org.junit.Assert.assertEquals; 40 import static org.junit.Assert.assertFalse; 41 import static org.junit.Assert.assertTrue; 42 import static org.junit.Assert.fail; 43 import static org.mockito.Mockito.atLeastOnce; 44 import static org.mockito.Mockito.verify; 45 46 /** 47 * System tests for video-specific behavior in telecom. 48 * TODO: Add unit tests which ensure that auto-speakerphone does not occur when using a wired 49 * headset or a bluetooth headset. 50 */ 51 @RunWith(JUnit4.class) 52 public class VideoCallTests extends TelecomSystemTest { 53 54 @Override 55 @Before setUp()56 public void setUp() throws Exception { 57 super.setUp(); 58 } 59 60 @Override 61 @After tearDown()62 public void tearDown() throws Exception { 63 super.tearDown(); 64 } 65 66 /** 67 * Tests to ensure an incoming video-call is automatically routed to the speakerphone when 68 * the call is answered and neither a wired headset nor bluetooth headset are connected. 69 */ 70 @MediumTest 71 @Test testAutoSpeakerphoneIncomingBidirectional()72 public void testAutoSpeakerphoneIncomingBidirectional() throws Exception { 73 // Start an incoming video call. 74 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 75 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, 76 VideoProfile.STATE_BIDIRECTIONAL); 77 78 verifyAudioRoute(CallAudioState.ROUTE_SPEAKER); 79 } 80 81 /** 82 * Tests to ensure an incoming receive-only video-call is answered in speakerphone mode. Note 83 * that this is not a scenario we would expect normally with the default dialer as it will 84 * always answer incoming video calls as bi-directional. It is, however, possible for a third 85 * party dialer to answer an incoming video call a a one-way video call. 86 */ 87 @MediumTest 88 @Test testAutoSpeakerphoneIncomingReceiveOnly()89 public void testAutoSpeakerphoneIncomingReceiveOnly() throws Exception { 90 // Start an incoming video call. 91 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 92 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, 93 VideoProfile.STATE_RX_ENABLED); 94 95 verifyAudioRoute(CallAudioState.ROUTE_SPEAKER); 96 } 97 98 /** 99 * Tests audio routing for an outgoing video call made with bidirectional video. Expect to be 100 * in speaker mode. 101 */ 102 @MediumTest 103 @Test testAutoSpeakerphoneOutgoingBidirectional()104 public void testAutoSpeakerphoneOutgoingBidirectional() throws Exception { 105 // Start an incoming video call. 106 IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", 107 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, 108 VideoProfile.STATE_BIDIRECTIONAL); 109 110 verifyAudioRoute(CallAudioState.ROUTE_SPEAKER); 111 } 112 113 /** 114 * Tests audio routing for an outgoing video call made with transmit only video. Expect to be 115 * in speaker mode. Note: The default UI does not support making one-way video calls, but the 116 * APIs do and a third party incall UI could choose to support that. 117 */ 118 @MediumTest 119 @Test testAutoSpeakerphoneOutgoingTransmitOnly()120 public void testAutoSpeakerphoneOutgoingTransmitOnly() throws Exception { 121 // Start an incoming video call. 122 IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", 123 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, 124 VideoProfile.STATE_TX_ENABLED); 125 126 verifyAudioRoute(CallAudioState.ROUTE_SPEAKER); 127 } 128 129 /** 130 * Tests audio routing for an outgoing video call made with transmit only video. Expect to be 131 * in speaker mode. Note: The default UI does not support making one-way video calls, but the 132 * APIs do and a third party incall UI could choose to support that. 133 */ 134 @MediumTest 135 @Test testNoAutoSpeakerphoneOnOutgoing()136 public void testNoAutoSpeakerphoneOnOutgoing() throws Exception { 137 // Start an incoming video call. 138 IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", 139 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, 140 VideoProfile.STATE_AUDIO_ONLY); 141 142 verifyAudioRoute(CallAudioState.ROUTE_EARPIECE); 143 } 144 145 /** 146 * Tests to ensure an incoming audio-only call is routed to the earpiece. 147 */ 148 @MediumTest 149 @Test testNoAutoSpeakerphoneOnIncoming()150 public void testNoAutoSpeakerphoneOnIncoming() throws Exception { 151 152 // Start an incoming video call. 153 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 154 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, 155 VideoProfile.STATE_AUDIO_ONLY); 156 157 verifyAudioRoute(CallAudioState.ROUTE_EARPIECE); 158 } 159 160 /** 161 * Ensure that when an incoming video call is missed, the video state history still includes 162 * video calling. This is important for the call log. 163 */ 164 @LargeTest 165 @Test testIncomingVideoCallMissedCheckVideoHistory()166 public void testIncomingVideoCallMissedCheckVideoHistory() throws Exception { 167 IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), 168 VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA); 169 com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls() 170 .iterator().next(); 171 172 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.MISSED); 173 174 assertTrue(VideoProfile.isVideo(call.getVideoStateHistory())); 175 } 176 177 /** 178 * Ensure that when an incoming video call is rejected, the video state history still includes 179 * video calling. This is important for the call log. 180 */ 181 @LargeTest 182 @Test testIncomingVideoCallRejectedCheckVideoHistory()183 public void testIncomingVideoCallRejectedCheckVideoHistory() throws Exception { 184 IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), 185 VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA); 186 com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls() 187 .iterator().next(); 188 189 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.REJECTED); 190 191 assertTrue(VideoProfile.isVideo(call.getVideoStateHistory())); 192 } 193 194 195 /** 196 * Ensure that when an outgoing video call is canceled, the video state history still includes 197 * video calling. This is important for the call log. 198 */ 199 @LargeTest 200 @Test testOutgoingVideoCallCanceledCheckVideoHistory()201 public void testOutgoingVideoCallCanceledCheckVideoHistory() throws Exception { 202 IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), 203 mConnectionServiceFixtureA, Process.myUserHandle(), 204 VideoProfile.STATE_BIDIRECTIONAL); 205 com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls() 206 .iterator().next(); 207 208 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 209 210 assertTrue(VideoProfile.isVideo(call.getVideoStateHistory())); 211 } 212 213 /** 214 * Ensure that when an outgoing video call is rejected, the video state history still includes 215 * video calling. This is important for the call log. 216 */ 217 @LargeTest 218 @Test testOutgoingVideoCallRejectedCheckVideoHistory()219 public void testOutgoingVideoCallRejectedCheckVideoHistory() throws Exception { 220 IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), 221 mConnectionServiceFixtureA, Process.myUserHandle(), 222 VideoProfile.STATE_BIDIRECTIONAL); 223 com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls() 224 .iterator().next(); 225 226 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.REMOTE); 227 228 assertTrue(VideoProfile.isVideo(call.getVideoStateHistory())); 229 } 230 231 /** 232 * Ensure that when an outgoing video call is answered as audio only, the video state history 233 * shows that the call was audio only. This is important for the call log. 234 */ 235 @LargeTest 236 @Test testOutgoingVideoCallAnsweredAsAudio()237 public void testOutgoingVideoCallAnsweredAsAudio() throws Exception { 238 IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), 239 mConnectionServiceFixtureA, Process.myUserHandle(), 240 VideoProfile.STATE_BIDIRECTIONAL); 241 com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls() 242 .iterator().next(); 243 244 mConnectionServiceFixtureA.mConnectionById.get(ids.mConnectionId).videoState 245 = VideoProfile.STATE_AUDIO_ONLY; 246 mConnectionServiceFixtureA.sendSetVideoState(ids.mConnectionId); 247 mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId); 248 249 assertFalse(VideoProfile.isVideo(call.getVideoStateHistory())); 250 } 251 252 /** 253 * Verifies that the 254 * {@link android.telecom.InCallService#onCallAudioStateChanged(CallAudioState)} change is 255 * called with an expected route and number of changes. 256 * 257 * @param expectedRoute The expected audio route on the latest change. 258 */ verifyAudioRoute(int expectedRoute)259 private void verifyAudioRoute(int expectedRoute) throws Exception { 260 // Capture all onCallAudioStateChanged callbacks to InCall. 261 CallAudioRouteStateMachine carsm = mTelecomSystem.getCallsManager() 262 .getCallAudioManager().getCallAudioRouteStateMachine(); 263 CallAudioModeStateMachine camsm = mTelecomSystem.getCallsManager() 264 .getCallAudioManager().getCallAudioModeStateMachine(); 265 waitForHandlerAction(camsm.getHandler(), TEST_TIMEOUT); 266 final boolean[] success = {true}; 267 carsm.sendMessage(CallAudioRouteStateMachine.RUN_RUNNABLE, (Runnable) () -> { 268 ArgumentCaptor<CallAudioState> callAudioStateArgumentCaptor = ArgumentCaptor.forClass( 269 CallAudioState.class); 270 try { 271 verify(mInCallServiceFixtureX.getTestDouble(), atLeastOnce()) 272 .onCallAudioStateChanged(callAudioStateArgumentCaptor.capture()); 273 } catch (RemoteException e) { 274 fail("Remote exception in InCallServiceFixture"); 275 } 276 List<CallAudioState> changes = callAudioStateArgumentCaptor.getAllValues(); 277 assertEquals(expectedRoute, changes.get(changes.size() - 1).getRoute()); 278 success[0] = true; 279 }); 280 waitForHandlerAction(carsm.getHandler(), TEST_TIMEOUT); 281 assertTrue(success[0]); 282 } 283 } 284