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