Merge "Add Video API unit tests, fix auto speakerphone logic."
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 46cd78e..1a80cfa 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -804,23 +804,26 @@
call.setHandle(uriHandle);
call.setGatewayInfo(gatewayInfo);
- // Auto-enable speakerphone if the originating intent specified to do so, or if the call
- // is a video call.
- call.setStartWithSpeakerphoneOn(speakerphoneOn || isSpeakerphoneAutoEnabled(videoState));
+
+ final boolean useSpeakerWhenDocked = mContext.getResources().getBoolean(
+ R.bool.use_speaker_when_docked);
+ final boolean isDocked = mDockManager.isDocked();
+ final boolean useSpeakerForVideoCall = isSpeakerphoneAutoEnabled(videoState);
+
+ // Auto-enable speakerphone if the originating intent specified to do so, if the call
+ // is a video call, of if using speaker when docked
+ call.setStartWithSpeakerphoneOn(speakerphoneOn || useSpeakerForVideoCall
+ || (useSpeakerWhenDocked && isDocked));
call.setVideoState(videoState);
if (speakerphoneOn) {
Log.i(this, "%s Starting with speakerphone as requested", call);
- } else {
+ } else if (useSpeakerWhenDocked && useSpeakerWhenDocked) {
Log.i(this, "%s Starting with speakerphone because car is docked.", call);
+ } else if (useSpeakerForVideoCall) {
+ Log.i(this, "%s Starting with speakerphone because its a video call.", call);
}
- final boolean useSpeakerWhenDocked = mContext.getResources().getBoolean(
- R.bool.use_speaker_when_docked);
-
- call.setStartWithSpeakerphoneOn(speakerphoneOn
- || (useSpeakerWhenDocked && mDockManager.isDocked()));
-
if (call.isEmergencyCall()) {
// Emergency -- CreateConnectionProcessor will choose accounts automatically
call.setTargetPhoneAccount(null);
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
new file mode 100644
index 0000000..9565cbd
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.telecom.tests;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.telecom.Analytics;
+import com.android.server.telecom.Log;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.os.Process;
+import android.telecom.Call;
+import android.telecom.CallAudioState;
+import android.telecom.Connection;
+import android.telecom.DisconnectCause;
+import android.telecom.ParcelableCall;
+import android.telecom.TelecomManager;
+import android.telecom.VideoProfile;
+
+import com.android.internal.telecom.IInCallAdapter;
+
+import java.io.StringWriter;
+import java.util.Map;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Performs various basic call tests in Telecom.
+ */
+public class BasicCallTests extends TelecomSystemTest {
+ public void testSingleOutgoingCallLocalDisconnect() throws Exception {
+ IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+ mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
+ assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+ assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+
+ mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
+ assertEquals(Call.STATE_DISCONNECTED,
+ mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+ assertEquals(Call.STATE_DISCONNECTED,
+ mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+ }
+
+ public void testSingleOutgoingCallRemoteDisconnect() throws Exception {
+ IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+ mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
+ assertEquals(Call.STATE_DISCONNECTED,
+ mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+ assertEquals(Call.STATE_DISCONNECTED,
+ mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+ }
+
+ /**
+ * Tests the {@link TelecomManager#acceptRingingCall()} API. Tests simple case of an incoming
+ * audio-only call.
+ *
+ * @throws Exception
+ */
+ public void testTelecomManagerAcceptRingingCall() throws Exception {
+ IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
+ mConnectionServiceFixtureA);
+
+ assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+ assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+
+ // Use TelecomManager API to answer the ringing call.
+ TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
+ .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
+ telecomManager.acceptRingingCall();
+
+ verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
+ .answer(ids.mCallId);
+ mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
+
+ mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
+ }
+
+ /**
+ * Tests the {@link TelecomManager#acceptRingingCall()} API. Tests simple case of an incoming
+ * video call, which should be answered as video.
+ *
+ * @throws Exception
+ */
+ public void testTelecomManagerAcceptRingingVideoCall() throws Exception {
+ IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
+ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+
+ assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+ assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+
+ // Use TelecomManager API to answer the ringing call; the default expected behavior is to
+ // answer using whatever video state the ringing call requests.
+ TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
+ .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
+ telecomManager.acceptRingingCall();
+
+ // Answer video API should be called
+ verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
+ .answerVideo(eq(ids.mCallId), eq(VideoProfile.STATE_BIDIRECTIONAL));
+ mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
+
+ mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
+ }
+
+ /**
+ * Tests the {@link TelecomManager#acceptRingingCall(int)} API. Tests answering a video call
+ * as an audio call.
+ *
+ * @throws Exception
+ */
+ public void testTelecomManagerAcceptRingingVideoCallAsAudio() throws Exception {
+ IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
+ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+
+ assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+ assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+
+ // Use TelecomManager API to answer the ringing call.
+ TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
+ .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
+ telecomManager.acceptRingingCall(VideoProfile.STATE_AUDIO_ONLY);
+
+ // The generic answer method on the ConnectionService is used to answer audio-only calls.
+ verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
+ .answer(eq(ids.mCallId));
+ mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
+
+ mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
+ }
+
+ /**
+ * Tests the {@link TelecomManager#acceptRingingCall()} API. Tests simple case of an incoming
+ * video call, where an attempt is made to answer with an invalid video state.
+ *
+ * @throws Exception
+ */
+ public void testTelecomManagerAcceptRingingInvalidVideoState() throws Exception {
+ IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
+ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+
+ assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+ assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+
+ // Use TelecomManager API to answer the ringing call; the default expected behavior is to
+ // answer using whatever video state the ringing call requests.
+ TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
+ .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
+ telecomManager.acceptRingingCall(999 /* invalid videostate */);
+
+ // Answer video API should be called
+ verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
+ .answerVideo(eq(ids.mCallId), eq(VideoProfile.STATE_BIDIRECTIONAL));
+ mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
+ mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
+ }
+
+ public void testSingleIncomingCallLocalDisconnect() throws Exception {
+ IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
+ assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+ assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+
+ mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
+ assertEquals(Call.STATE_DISCONNECTED,
+ mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+ assertEquals(Call.STATE_DISCONNECTED,
+ mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+ }
+
+ public void testSingleIncomingCallRemoteDisconnect() throws Exception {
+ IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+ mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
+ assertEquals(Call.STATE_DISCONNECTED,
+ mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+ assertEquals(Call.STATE_DISCONNECTED,
+ mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+ }
+
+ public void do_testDeadlockOnOutgoingCall() throws Exception {
+ final IdPair ids = startOutgoingPhoneCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
+ Process.myUserHandle());
+ rapidFire(
+ new Runnable() {
+ @Override
+ public void run() {
+ while (mCallerInfoAsyncQueryFactoryFixture.mRequests.size() > 0) {
+ mCallerInfoAsyncQueryFactoryFixture.mRequests.remove(0).reply();
+ }
+ }
+ },
+ new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
+ } catch (Exception e) {
+ Log.e(this, e, "");
+ }
+ }
+ });
+ }
+
+ public void testDeadlockOnOutgoingCall() throws Exception {
+ for (int i = 0; i < 100; i++) {
+ BasicCallTests test = new BasicCallTests();
+ test.setContext(getContext());
+ test.setTestContext(getTestContext());
+ test.setName(getName());
+ test.setUp();
+ test.do_testDeadlockOnOutgoingCall();
+ test.tearDown();
+ }
+ }
+
+ public void testIncomingThenOutgoingCalls() throws Exception {
+ // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
+ IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+ mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId);
+ mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId);
+ }
+
+ public void testOutgoingThenIncomingCalls() throws Exception {
+ // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
+ IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ verify(mConnectionServiceFixtureA.getTestDouble())
+ .hold(outgoing.mConnectionId);
+ mConnectionServiceFixtureA.mConnectionById.get(outgoing.mConnectionId).state =
+ Connection.STATE_HOLDING;
+ mConnectionServiceFixtureA.sendSetOnHold(outgoing.mConnectionId);
+ assertEquals(Call.STATE_HOLDING,
+ mInCallServiceFixtureX.getCall(outgoing.mCallId).getState());
+ assertEquals(Call.STATE_HOLDING,
+ mInCallServiceFixtureY.getCall(outgoing.mCallId).getState());
+
+ mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId);
+ mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId);
+ }
+
+ public void testAudioManagerOperations() throws Exception {
+ AudioManager audioManager = (AudioManager) mComponentContextFixture.getTestDouble()
+ .getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
+
+ IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+ verify(audioManager, timeout(TEST_TIMEOUT)).requestAudioFocusForCall(anyInt(), anyInt());
+ verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce())
+ .setMode(AudioManager.MODE_IN_CALL);
+
+ mInCallServiceFixtureX.mInCallAdapter.mute(true);
+ verify(mAudioService, timeout(TEST_TIMEOUT))
+ .setMicrophoneMute(eq(true), any(String.class), any(Integer.class));
+ mInCallServiceFixtureX.mInCallAdapter.mute(false);
+ verify(mAudioService, timeout(TEST_TIMEOUT))
+ .setMicrophoneMute(eq(false), any(String.class), any(Integer.class));
+
+ mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER);
+ verify(audioManager, timeout(TEST_TIMEOUT))
+ .setSpeakerphoneOn(true);
+ mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE);
+ verify(audioManager, timeout(TEST_TIMEOUT))
+ .setSpeakerphoneOn(false);
+
+ mConnectionServiceFixtureA.
+ sendSetDisconnected(outgoing.mConnectionId, DisconnectCause.REMOTE);
+
+ verify(audioManager, timeout(TEST_TIMEOUT))
+ .abandonAudioFocusForCall();
+ verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce())
+ .setMode(AudioManager.MODE_NORMAL);
+ }
+
+ private void rapidFire(Runnable... tasks) {
+ final CyclicBarrier barrier = new CyclicBarrier(tasks.length);
+ final CountDownLatch latch = new CountDownLatch(tasks.length);
+ for (int i = 0; i < tasks.length; i++) {
+ final Runnable task = tasks[i];
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ barrier.await();
+ task.run();
+ } catch (InterruptedException | BrokenBarrierException e){
+ Log.e(BasicCallTests.this, e, "Unexpectedly interrupted");
+ } finally {
+ latch.countDown();
+ }
+ }
+ }).start();
+ }
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ Log.e(BasicCallTests.this, e, "Unexpectedly interrupted");
+ }
+ }
+
+ public void testBasicConferenceCall() throws Exception {
+ makeConferenceCall();
+ }
+
+ public void testAddCallToConference1() throws Exception {
+ ParcelableCall conferenceCall = makeConferenceCall();
+ IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ // testAddCallToConference{1,2} differ in the order of arguments to InCallAdapter#conference
+ mInCallServiceFixtureX.getInCallAdapter().conference(
+ conferenceCall.getId(), callId3.mCallId);
+ Thread.sleep(200);
+
+ ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId);
+ ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId());
+ assertEquals(conferenceCall.getId(), call3.getParentCallId());
+ assertEquals(3, updatedConference.getChildCallIds().size());
+ assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId));
+ }
+
+ public void testAddCallToConference2() throws Exception {
+ ParcelableCall conferenceCall = makeConferenceCall();
+ IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ mInCallServiceFixtureX.getInCallAdapter()
+ .conference(callId3.mCallId, conferenceCall.getId());
+ Thread.sleep(200);
+
+ ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId);
+ ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId());
+ assertEquals(conferenceCall.getId(), call3.getParentCallId());
+ assertEquals(3, updatedConference.getChildCallIds().size());
+ assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId));
+ }
+
+ private ParcelableCall makeConferenceCall() throws Exception {
+ IdPair callId1 = startAndMakeActiveOutgoingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+ IdPair callId2 = startAndMakeActiveOutgoingCall("650-555-1213",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+ IInCallAdapter inCallAdapter = mInCallServiceFixtureX.getInCallAdapter();
+ inCallAdapter.conference(callId1.mCallId, callId2.mCallId);
+ // Wait for wacky non-deterministic behavior
+ Thread.sleep(200);
+ ParcelableCall call1 = mInCallServiceFixtureX.getCall(callId1.mCallId);
+ ParcelableCall call2 = mInCallServiceFixtureX.getCall(callId2.mCallId);
+ // Check that the two calls end up with a parent in the end
+ assertNotNull(call1.getParentCallId());
+ assertNotNull(call2.getParentCallId());
+ assertEquals(call1.getParentCallId(), call2.getParentCallId());
+
+ // Check to make sure that the parent call made it to the in-call service
+ String parentCallId = call1.getParentCallId();
+ ParcelableCall conferenceCall = mInCallServiceFixtureX.getCall(parentCallId);
+ assertEquals(2, conferenceCall.getChildCallIds().size());
+ assertTrue(conferenceCall.getChildCallIds().contains(callId1.mCallId));
+ assertTrue(conferenceCall.getChildCallIds().contains(callId2.mCallId));
+ return conferenceCall;
+ }
+
+ public void testAnalyticsSingleCall() throws Exception {
+ IdPair testCall = startAndMakeActiveIncomingCall(
+ "650-555-1212",
+ mPhoneAccountA0.getAccountHandle(),
+ mConnectionServiceFixtureA);
+ Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
+
+ assertTrue(analyticsMap.containsKey(testCall.mCallId));
+
+ Analytics.CallInfoImpl callAnalytics = analyticsMap.get(testCall.mCallId);
+ assertTrue(callAnalytics.startTime > 0);
+ assertEquals(0, callAnalytics.endTime);
+ assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics.callDirection);
+ assertFalse(callAnalytics.isInterrupted);
+ assertNull(callAnalytics.callTerminationReason);
+ assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
+ callAnalytics.connectionService);
+
+ mConnectionServiceFixtureA.
+ sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR);
+
+ analyticsMap = Analytics.cloneData();
+ callAnalytics = analyticsMap.get(testCall.mCallId);
+ assertTrue(callAnalytics.endTime > 0);
+ assertNotNull(callAnalytics.callTerminationReason);
+ assertEquals(DisconnectCause.ERROR, callAnalytics.callTerminationReason.getCode());
+
+ StringWriter sr = new StringWriter();
+ IndentingPrintWriter ip = new IndentingPrintWriter(sr, " ");
+ Analytics.dump(ip);
+ String dumpResult = sr.toString();
+ String[] expectedFields = {"startTime", "endTime", "direction", "isAdditionalCall",
+ "isInterrupted", "callTechnologies", "callTerminationReason", "connectionServices"};
+ for (String field : expectedFields) {
+ assertTrue(dumpResult.contains(field));
+ }
+ }
+
+ public void testAnalyticsTwoCalls() throws Exception {
+ IdPair testCall1 = startAndMakeActiveIncomingCall(
+ "650-555-1212",
+ mPhoneAccountA0.getAccountHandle(),
+ mConnectionServiceFixtureA);
+ IdPair testCall2 = startAndMakeActiveOutgoingCall(
+ "650-555-1213",
+ mPhoneAccountA0.getAccountHandle(),
+ mConnectionServiceFixtureA);
+
+ Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
+ assertTrue(analyticsMap.containsKey(testCall1.mCallId));
+ assertTrue(analyticsMap.containsKey(testCall2.mCallId));
+
+ Analytics.CallInfoImpl callAnalytics1 = analyticsMap.get(testCall1.mCallId);
+ Analytics.CallInfoImpl callAnalytics2 = analyticsMap.get(testCall2.mCallId);
+ assertTrue(callAnalytics1.startTime > 0);
+ assertTrue(callAnalytics2.startTime > 0);
+ assertEquals(0, callAnalytics1.endTime);
+ assertEquals(0, callAnalytics2.endTime);
+
+ assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics1.callDirection);
+ assertEquals(Analytics.OUTGOING_DIRECTION, callAnalytics2.callDirection);
+
+ assertTrue(callAnalytics1.isInterrupted);
+ assertTrue(callAnalytics2.isAdditionalCall);
+
+ assertNull(callAnalytics1.callTerminationReason);
+ assertNull(callAnalytics2.callTerminationReason);
+
+ assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
+ callAnalytics1.connectionService);
+ assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
+ callAnalytics1.connectionService);
+
+ mConnectionServiceFixtureA.
+ sendSetDisconnected(testCall2.mConnectionId, DisconnectCause.REMOTE);
+ mConnectionServiceFixtureA.
+ sendSetDisconnected(testCall1.mConnectionId, DisconnectCause.ERROR);
+
+ analyticsMap = Analytics.cloneData();
+ callAnalytics1 = analyticsMap.get(testCall1.mCallId);
+ callAnalytics2 = analyticsMap.get(testCall2.mCallId);
+ assertTrue(callAnalytics1.endTime > 0);
+ assertTrue(callAnalytics2.endTime > 0);
+ assertNotNull(callAnalytics1.callTerminationReason);
+ assertNotNull(callAnalytics2.callTerminationReason);
+ assertEquals(DisconnectCause.ERROR, callAnalytics1.callTerminationReason.getCode());
+ assertEquals(DisconnectCause.REMOTE, callAnalytics2.callTerminationReason.getCode());
+ }
+}
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
index 0e16986..8ea3fbe 100644
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
@@ -64,19 +64,19 @@
@Override
public Connection onCreateUnknownConnection(
PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) {
- return new FakeConnection();
+ return new FakeConnection(request.getVideoState());
}
@Override
public Connection onCreateIncomingConnection(
PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) {
- return new FakeConnection();
+ return new FakeConnection(request.getVideoState());
}
@Override
public Connection onCreateOutgoingConnection(
PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) {
- return new FakeConnection();
+ return new FakeConnection(request.getVideoState());
}
@Override
@@ -92,12 +92,13 @@
}
public class FakeConnection extends Connection {
- public FakeConnection() {
+ public FakeConnection(int videoState) {
super();
int capabilities = getConnectionCapabilities();
capabilities |= CAPABILITY_MUTE;
capabilities |= CAPABILITY_SUPPORT_HOLD;
capabilities |= CAPABILITY_HOLD;
+ setVideoState(videoState);
setConnectionCapabilities(capabilities);
setActive();
}
@@ -158,6 +159,9 @@
c.isIncoming = isIncoming;
c.isUnknown = isUnknown;
c.capabilities |= Connection.CAPABILITY_HOLD | Connection.CAPABILITY_SUPPORT_HOLD;
+ c.videoState = request.getVideoState();
+ c.mockVideoProvider = new MockVideoProvider();
+ c.videoProvider = c.mockVideoProvider.getInterface();
mConnectionById.put(id, c);
mConnectionServiceDelegateAdapter.createConnection(connectionManagerPhoneAccount,
id, request, isIncoming, isUnknown);
@@ -253,6 +257,8 @@
int callerDisplayNamePresentation;
final List<String> conferenceableConnectionIds = new ArrayList<>();
IVideoProvider videoProvider;
+ Connection.VideoProvider videoProviderImpl;
+ MockVideoProvider mockVideoProvider;
int videoState;
boolean isVoipAudioMode;
Bundle extras;
diff --git a/tests/src/com/android/server/telecom/tests/MockVideoProvider.java b/tests/src/com/android/server/telecom/tests/MockVideoProvider.java
new file mode 100644
index 0000000..147d232
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/MockVideoProvider.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.telecom.tests;
+
+import org.mockito.Mockito;
+
+import android.net.Uri;
+import android.telecom.Connection;
+import android.telecom.Connection.VideoProvider;
+import android.telecom.InCallService;
+import android.telecom.InCallService.VideoCall;
+import android.telecom.Log;
+import android.telecom.VideoProfile;
+import android.view.Surface;
+
+/**
+ * Provides a mock implementation of a video provider.
+ */
+public class MockVideoProvider extends VideoProvider {
+ public static final String CAMERA_NONE = "none";
+ public static final String CAMERA_FRONT = "front";
+ public static final String CAMERA_BACK = "back";
+ public static final int CAMERA_FRONT_DIMENSIONS = 1024;
+ public static final int CAMERA_BACK_DIMENSIONS = 2048;
+ public static final long DATA_USAGE = 1024;
+ public static final int PEER_DIMENSIONS = 4096;
+ public static final int DEVICE_ORIENTATION_UNDEFINED = -1;
+ public static final float ZOOM_UNDEFINED = -1.0f;
+
+ private Surface mPreviewSurface = null;
+ private Surface mDisplaySurface = null;
+ private int mDeviceOrientation = DEVICE_ORIENTATION_UNDEFINED;
+ private float mZoom = ZOOM_UNDEFINED;
+ private VideoProfile mSessionModifyResponse = null;
+ private Uri mPauseImage = null;
+
+ /**
+ * Responds to a request to set the camera by reporting the new camera information via the
+ * {@link #changeCameraCapabilities(VideoProfile.CameraCapabilities)} API.
+ *
+ * @param cameraId The id of the camera (use ids as reported by
+ */
+ @Override
+ public void onSetCamera(String cameraId) {
+ handleCameraChange(cameraId);
+ }
+
+ /**
+ * Stores the preview surface set via the {@link VideoCall#setPreviewSurface(Surface)} API for
+ * retrieval using {@link #getPreviewSurface()}.
+ *
+ * @param surface The {@link Surface}.
+ */
+ @Override
+ public void onSetPreviewSurface(Surface surface) {
+ mPreviewSurface = surface;
+ }
+
+ /**
+ * Stores the display surface set via the {@link VideoCall#setDisplaySurface(Surface)} API for
+ * retrieval using {@link #getDisplaySurface()}.
+ *
+ * @param surface The {@link Surface}.
+ */
+ @Override
+ public void onSetDisplaySurface(Surface surface) {
+ mDisplaySurface = surface;
+ }
+
+ /**
+ * Stores the device orientation set via the {@link VideoCall#setDeviceOrientation(int)} API for
+ * retrieval using {@link #getDeviceOrientation()}.
+ *
+ * @param rotation The device orientation, in degrees.
+ */
+ @Override
+ public void onSetDeviceOrientation(int rotation) {
+ mDeviceOrientation = rotation;
+ }
+
+ /**
+ * Stores the zoom level set via the {@link VideoCall#setZoom(float)} API for retrieval using
+ * {@link #getZoom()}.
+ *
+ * @param value The camera zoom.
+ */
+ @Override
+ public void onSetZoom(float value) {
+ mZoom = value;
+ }
+
+ /**
+ * Responds to any incoming session modify request by accepting the requested profile.
+ *
+ * @param fromProfile The video profile prior to the request.
+ * @param toProfile The video profile with the requested changes made.
+ */
+ @Override
+ public void onSendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
+ super.receiveSessionModifyResponse(VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS,
+ fromProfile, toProfile);
+ }
+
+ /**
+ * Stores session modify responses received via the
+ * {@link VideoCall#sendSessionModifyResponse(VideoProfile)} API for retrieval via
+ * {@link #getSessionModifyResponse()}.
+ *
+ * @param responseProfile The response video profile.
+ */
+ @Override
+ public void onSendSessionModifyResponse(VideoProfile responseProfile) {
+ mSessionModifyResponse = responseProfile;
+ }
+
+ /**
+ * Responds to requests for camera capabilities by reporting the front camera capabilities.
+ */
+ @Override
+ public void onRequestCameraCapabilities() {
+ handleCameraChange(CAMERA_FRONT);
+ }
+
+ /**
+ * Responds to all requests for data usage by reporting {@link #DATA_USAGE}.
+ */
+ @Override
+ public void onRequestConnectionDataUsage() {
+ super.setCallDataUsage(DATA_USAGE);
+ }
+
+ /**
+ * Stores pause image URIs received via the {@link VideoCall#setPauseImage(Uri)} API for
+ * retrieval via {@link #getPauseImage()}.
+ *
+ * @param uri URI of image to display.
+ */
+ @Override
+ public void onSetPauseImage(Uri uri) {
+ mPauseImage = uri;
+ }
+
+ /**
+ * Handles a change to the current camera selection. Responds by reporting the capabilities of
+ * the camera.
+ */
+ private void handleCameraChange(String cameraId) {
+ if (CAMERA_FRONT.equals(cameraId)) {
+ super.changeCameraCapabilities(new VideoProfile.CameraCapabilities(
+ CAMERA_FRONT_DIMENSIONS, CAMERA_FRONT_DIMENSIONS));
+ } else if (CAMERA_BACK.equals(cameraId)) {
+ super.changeCameraCapabilities(new VideoProfile.CameraCapabilities(
+ CAMERA_BACK_DIMENSIONS, CAMERA_BACK_DIMENSIONS));
+ }
+ }
+
+ /**
+ * Retrieves the last preview surface sent to the provider.
+ *
+ * @return the surface.
+ */
+ public Surface getPreviewSurface() {
+ return mPreviewSurface;
+ }
+
+ /**
+ * Retrieves the last display surface sent to the provider.
+ *
+ * @return the surface.
+ */
+ public Surface getDisplaySurface() {
+ return mDisplaySurface;
+ }
+
+ /**
+ * Retrieves the last device orientation sent to the provider.
+ *
+ * @return the orientation.
+ */
+ public int getDeviceOrientation() {
+ return mDeviceOrientation;
+ }
+
+ /**
+ * Retrieves the last zoom sent to the provider.
+ *
+ * @return the zoom.
+ */
+ public float getZoom() {
+ return mZoom;
+ }
+
+ /**
+ * Retrieves the last session modify response sent to the provider.
+ *
+ * @return the session modify response.
+ */
+ public VideoProfile getSessionModifyResponse() {
+ return mSessionModifyResponse;
+ }
+
+ /**
+ * Retrieves the last pause image sent to the provider.
+ *
+ * @return the pause image URI.
+ */
+ public Uri getPauseImage() {
+ return mPauseImage;
+ }
+
+ /**
+ * Sends a mock session modify request via the provider.
+ */
+ public void sendMockSessionModifyRequest() {
+ super.receiveSessionModifyRequest(new VideoProfile(VideoProfile.STATE_BIDIRECTIONAL));
+ }
+
+ /**
+ * Sends a mock session event via the provider.
+ *
+ * @param event the event.
+ */
+ public void sendMockSessionEvent(int event) {
+ super.handleCallSessionEvent(event);
+ }
+
+ /**
+ * Sends a mock peer dimension change via the provider.
+ *
+ * @param width The new width.
+ * @param height The new height.
+ */
+ public void sendMockPeerDimensions(int width, int height) {
+ super.changePeerDimensions(width, height);
+ }
+
+ /**
+ * Sends a mock video quality change via the provider.
+ *
+ * @param videoQuality the video quality.
+ */
+ public void sendMockVideoQuality(int videoQuality) {
+ super.changeVideoQuality(videoQuality);
+ }
+}
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index 7ebbb63..a4a8397 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -49,6 +49,7 @@
import android.telecom.Connection;
import android.telecom.ConnectionRequest;
import android.telecom.DisconnectCause;
+import android.telecom.InCallService;
import android.telecom.ParcelableCall;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
@@ -56,8 +57,8 @@
import android.telecom.VideoProfile;
import com.android.internal.telecom.IInCallAdapter;
+import com.android.internal.telecom.IVideoProvider;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.telecom.Analytics;
import com.android.server.telecom.BluetoothPhoneServiceImpl;
import com.android.server.telecom.CallAudioManager;
import com.android.server.telecom.CallIntentProcessor;
@@ -82,6 +83,7 @@
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -91,6 +93,9 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
+/**
+ * Implements mocks and functionality required to implement telecom system tests.
+ */
public class TelecomSystemTest extends TelecomTestCase {
static final int TEST_POLL_INTERVAL = 10; // milliseconds
@@ -302,11 +307,9 @@
mConnectionServiceFixtureA = new ConnectionServiceFixture();
mConnectionServiceFixtureB = new ConnectionServiceFixture();
- mComponentContextFixture.addConnectionService(
- mConnectionServiceComponentNameA,
+ mComponentContextFixture.addConnectionService(mConnectionServiceComponentNameA,
mConnectionServiceFixtureA.getTestDouble());
- mComponentContextFixture.addConnectionService(
- mConnectionServiceComponentNameB,
+ mComponentContextFixture.addConnectionService(mConnectionServiceComponentNameB,
mConnectionServiceFixtureB.getTestDouble());
mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA0);
@@ -330,11 +333,9 @@
mInCallServiceFixtureX = new InCallServiceFixture();
mInCallServiceFixtureY = new InCallServiceFixture();
- mComponentContextFixture.addInCallService(
- mInCallServiceComponentNameX,
+ mComponentContextFixture.addInCallService(mInCallServiceComponentNameX,
mInCallServiceFixtureX.getTestDouble());
- mComponentContextFixture.addInCallService(
- mInCallServiceComponentNameY,
+ mComponentContextFixture.addInCallService(mInCallServiceComponentNameY,
mInCallServiceFixtureY.getTestDouble());
}
@@ -368,21 +369,22 @@
return audioService;
}
- private IdPair startOutgoingPhoneCall(
- String number,
- PhoneAccountHandle phoneAccountHandle,
- ConnectionServiceFixture connectionServiceFixture,
- UserHandle initiatingUser) throws Exception {
- reset(
- connectionServiceFixture.getTestDouble(),
- mInCallServiceFixtureX.getTestDouble(),
+ protected IdPair startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle,
+ ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser)
+ throws Exception {
+ return startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
+ initiatingUser, VideoProfile.STATE_AUDIO_ONLY);
+ }
+
+ protected IdPair startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle,
+ ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
+ int videoState) throws Exception {
+ reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(),
mInCallServiceFixtureY.getTestDouble());
- assertEquals(
- mInCallServiceFixtureX.mCallById.size(),
+ assertEquals(mInCallServiceFixtureX.mCallById.size(),
mInCallServiceFixtureY.mCallById.size());
- assertEquals(
- (mInCallServiceFixtureX.mInCallAdapter != null),
+ assertEquals((mInCallServiceFixtureX.mInCallAdapter != null),
(mInCallServiceFixtureY.mInCallAdapter != null));
mNumOutgoingCallsMade++;
@@ -399,6 +401,9 @@
TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
phoneAccountHandle);
}
+ if (videoState != VideoProfile.STATE_AUDIO_ONLY) {
+ actionCallIntent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState);
+ }
final UserHandle userHandle = initiatingUser;
Context localAppContext = mComponentContextFixture.getTestDouble().getApplicationContext();
@@ -443,35 +448,27 @@
new BroadcastReceiver.PendingResult(0, "", null, 0, true, false, null, 0, 0));
newOutgoingCallReceiver.getValue().setResultData(
newOutgoingCallIntent.getValue().getStringExtra(Intent.EXTRA_PHONE_NUMBER));
- newOutgoingCallReceiver.getValue().onReceive(
- mComponentContextFixture.getTestDouble(),
+ newOutgoingCallReceiver.getValue().onReceive(mComponentContextFixture.getTestDouble(),
newOutgoingCallIntent.getValue());
assertEquals(startingNumConnections + 1, connectionServiceFixture.mConnectionById.size());
- verify(connectionServiceFixture.getTestDouble()).createConnection(
- eq(phoneAccountHandle),
- anyString(),
- any(ConnectionRequest.class),
- anyBoolean(),
- anyBoolean());
-
+ verify(connectionServiceFixture.getTestDouble())
+ .createConnection(eq(phoneAccountHandle), anyString(), any(ConnectionRequest.class),
+ anyBoolean(), anyBoolean());
connectionServiceFixture.sendHandleCreateConnectionComplete(
connectionServiceFixture.mLatestConnectionId);
assertEquals(startingNumCalls + 1, mInCallServiceFixtureX.mCallById.size());
assertEquals(startingNumCalls + 1, mInCallServiceFixtureY.mCallById.size());
- assertEquals(
- mInCallServiceFixtureX.mLatestCallId,
- mInCallServiceFixtureY.mLatestCallId);
+ assertEquals(mInCallServiceFixtureX.mLatestCallId, mInCallServiceFixtureY.mLatestCallId);
- return new IdPair(
- connectionServiceFixture.mLatestConnectionId,
+ return new IdPair(connectionServiceFixture.mLatestConnectionId,
mInCallServiceFixtureX.mLatestCallId);
}
- private IdPair startIncomingPhoneCall(
+ protected IdPair startIncomingPhoneCall(
String number,
PhoneAccountHandle phoneAccountHandle,
final ConnectionServiceFixture connectionServiceFixture) throws Exception {
@@ -479,23 +476,18 @@
connectionServiceFixture);
}
- private IdPair startIncomingPhoneCall(
+ protected IdPair startIncomingPhoneCall(
String number,
PhoneAccountHandle phoneAccountHandle,
int videoState,
final ConnectionServiceFixture connectionServiceFixture) throws Exception {
- reset(
- connectionServiceFixture.getTestDouble(),
- mInCallServiceFixtureX.getTestDouble(),
+ reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(),
mInCallServiceFixtureY.getTestDouble());
- assertEquals(
- mInCallServiceFixtureX.mCallById.size(),
+ assertEquals(mInCallServiceFixtureX.mCallById.size(),
mInCallServiceFixtureY.mCallById.size());
- assertEquals(
- (mInCallServiceFixtureX.mInCallAdapter != null),
+ assertEquals((mInCallServiceFixtureX.mInCallAdapter != null),
(mInCallServiceFixtureY.mInCallAdapter != null));
-
final int startingNumConnections = connectionServiceFixture.mConnectionById.size();
final int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null;
@@ -507,22 +499,17 @@
mTelecomSystem.getTelecomServiceImpl().getBinder()
.addNewIncomingCall(phoneAccountHandle, extras);
- verify(connectionServiceFixture.getTestDouble()).createConnection(
- any(PhoneAccountHandle.class),
- anyString(),
- any(ConnectionRequest.class),
- eq(true),
- eq(false));
+ verify(connectionServiceFixture.getTestDouble())
+ .createConnection(any(PhoneAccountHandle.class), anyString(),
+ any(ConnectionRequest.class), eq(true), eq(false));
mConnectionServiceFixtureA.mConnectionById.get(
connectionServiceFixture.mLatestConnectionId).videoState = videoState;
connectionServiceFixture.sendHandleCreateConnectionComplete(
connectionServiceFixture.mLatestConnectionId);
- connectionServiceFixture.sendSetRinging(
- connectionServiceFixture.mLatestConnectionId);
- connectionServiceFixture.sendSetVideoState(
- connectionServiceFixture.mLatestConnectionId);
+ connectionServiceFixture.sendSetRinging(connectionServiceFixture.mLatestConnectionId);
+ connectionServiceFixture.sendSetVideoState(connectionServiceFixture.mLatestConnectionId);
// For the case of incoming calls, Telecom connecting the InCall services and adding the
// Call is triggered by the async completion of the CallerInfoAsyncQuery. Once the Call
@@ -530,16 +517,10 @@
// test fixtures, will be synchronous.
if (!hasInCallAdapter) {
- verify(
- mInCallServiceFixtureX.getTestDouble(),
- timeout(TEST_TIMEOUT))
- .setInCallAdapter(
- any(IInCallAdapter.class));
- verify(
- mInCallServiceFixtureY.getTestDouble(),
- timeout(TEST_TIMEOUT))
- .setInCallAdapter(
- any(IInCallAdapter.class));
+ verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
+ .setInCallAdapter(any(IInCallAdapter.class));
+ verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
+ .setInCallAdapter(any(IInCallAdapter.class));
}
// Give the InCallService time to respond
@@ -558,16 +539,10 @@
}
});
- verify(
- mInCallServiceFixtureX.getTestDouble(),
- timeout(TEST_TIMEOUT))
- .addCall(
- any(ParcelableCall.class));
- verify(
- mInCallServiceFixtureY.getTestDouble(),
- timeout(TEST_TIMEOUT))
- .addCall(
- any(ParcelableCall.class));
+ verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
+ .addCall(any(ParcelableCall.class));
+ verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
+ .addCall(any(ParcelableCall.class));
// Give the InCallService time to respond
@@ -591,54 +566,35 @@
}
});
- assertEquals(
- mInCallServiceFixtureX.mLatestCallId,
- mInCallServiceFixtureY.mLatestCallId);
+ assertEquals(mInCallServiceFixtureX.mLatestCallId, mInCallServiceFixtureY.mLatestCallId);
- return new IdPair(
- connectionServiceFixture.mLatestConnectionId,
+ return new IdPair(connectionServiceFixture.mLatestConnectionId,
mInCallServiceFixtureX.mLatestCallId);
}
- private void rapidFire(Runnable... tasks) {
- final CyclicBarrier barrier = new CyclicBarrier(tasks.length);
- final CountDownLatch latch = new CountDownLatch(tasks.length);
- for (int i = 0; i < tasks.length; i++) {
- final Runnable task = tasks[i];
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- barrier.await();
- task.run();
- } catch (InterruptedException | BrokenBarrierException e){
- Log.e(TelecomSystemTest.this, e, "Unexpectedly interrupted");
- } finally {
- latch.countDown();
- }
- }
- }).start();
- }
- try {
- latch.await();
- } catch (InterruptedException e) {
- Log.e(TelecomSystemTest.this, e, "Unexpectedly interrupted");
- }
+ protected IdPair startAndMakeActiveOutgoingCall(
+ String number,
+ PhoneAccountHandle phoneAccountHandle,
+ ConnectionServiceFixture connectionServiceFixture) throws Exception {
+ return startAndMakeActiveOutgoingCall(number, phoneAccountHandle, connectionServiceFixture,
+ VideoProfile.STATE_AUDIO_ONLY);
}
// A simple outgoing call, verifying that the appropriate connection service is contacted,
// the proper lifecycle is followed, and both In-Call Services are updated correctly.
- private IdPair startAndMakeActiveOutgoingCall(
+ protected IdPair startAndMakeActiveOutgoingCall(
String number,
PhoneAccountHandle phoneAccountHandle,
- ConnectionServiceFixture connectionServiceFixture) throws Exception {
+ ConnectionServiceFixture connectionServiceFixture, int videoState) throws Exception {
IdPair ids = startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
- Process.myUserHandle());
+ Process.myUserHandle(), videoState);
connectionServiceFixture.sendSetDialing(ids.mConnectionId);
assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_DIALING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+ connectionServiceFixture.sendSetVideoState(ids.mConnectionId);
+
connectionServiceFixture.sendSetActive(ids.mConnectionId);
assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
@@ -646,214 +602,35 @@
return ids;
}
- public void testBasicConferenceCall() throws Exception {
- makeConferenceCall();
- }
-
- public void testAddCallToConference1() throws Exception {
- ParcelableCall conferenceCall = makeConferenceCall();
- IdPair callId3 = startAndMakeActiveOutgoingCall(
- "650-555-1214",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
- // testAddCallToConference{1,2} differ in the order of arguments to InCallAdapter#conference
- mInCallServiceFixtureX.getInCallAdapter().conference(
- conferenceCall.getId(), callId3.mCallId);
- Thread.sleep(200);
-
- ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId);
- ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId());
- assertEquals(conferenceCall.getId(), call3.getParentCallId());
- assertEquals(3, updatedConference.getChildCallIds().size());
- assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId));
- }
-
- public void testAddCallToConference2() throws Exception {
- ParcelableCall conferenceCall = makeConferenceCall();
- IdPair callId3 = startAndMakeActiveOutgoingCall(
- "650-555-1214",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
- mInCallServiceFixtureX.getInCallAdapter().conference(
- callId3.mCallId, conferenceCall.getId());
- Thread.sleep(200);
-
- ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId);
- ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId());
- assertEquals(conferenceCall.getId(), call3.getParentCallId());
- assertEquals(3, updatedConference.getChildCallIds().size());
- assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId));
- }
-
- private ParcelableCall makeConferenceCall() throws Exception {
- IdPair callId1 = startAndMakeActiveOutgoingCall(
- "650-555-1212",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
-
- IdPair callId2 = startAndMakeActiveOutgoingCall(
- "650-555-1213",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
-
- IInCallAdapter inCallAdapter = mInCallServiceFixtureX.getInCallAdapter();
- inCallAdapter.conference(callId1.mCallId, callId2.mCallId);
- // Wait for wacky non-deterministic behavior
- Thread.sleep(200);
- ParcelableCall call1 = mInCallServiceFixtureX.getCall(callId1.mCallId);
- ParcelableCall call2 = mInCallServiceFixtureX.getCall(callId2.mCallId);
- // Check that the two calls end up with a parent in the end
- assertNotNull(call1.getParentCallId());
- assertNotNull(call2.getParentCallId());
- assertEquals(call1.getParentCallId(), call2.getParentCallId());
-
- // Check to make sure that the parent call made it to the in-call service
- String parentCallId = call1.getParentCallId();
- ParcelableCall conferenceCall = mInCallServiceFixtureX.getCall(parentCallId);
- assertEquals(2, conferenceCall.getChildCallIds().size());
- assertTrue(conferenceCall.getChildCallIds().contains(callId1.mCallId));
- assertTrue(conferenceCall.getChildCallIds().contains(callId2.mCallId));
- return conferenceCall;
- }
-
- public void testSingleOutgoingCallLocalDisconnect() throws Exception {
- IdPair ids = startAndMakeActiveOutgoingCall(
- "650-555-1212",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
-
- mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
- assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
- assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-
- mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
- assertEquals(Call.STATE_DISCONNECTED,
- mInCallServiceFixtureX.getCall(ids.mCallId).getState());
- assertEquals(Call.STATE_DISCONNECTED,
- mInCallServiceFixtureY.getCall(ids.mCallId).getState());
- }
-
- public void testSingleOutgoingCallRemoteDisconnect() throws Exception {
- IdPair ids = startAndMakeActiveOutgoingCall(
- "650-555-1212",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
-
- mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
- assertEquals(Call.STATE_DISCONNECTED,
- mInCallServiceFixtureX.getCall(ids.mCallId).getState());
- assertEquals(Call.STATE_DISCONNECTED,
- mInCallServiceFixtureY.getCall(ids.mCallId).getState());
- }
-
- /**
- * Tests the {@link TelecomManager#acceptRingingCall()} API. Tests simple case of an incoming
- * audio-only call.
- *
- * @throws Exception
- */
- public void testTelecomManagerAcceptRingingCall() throws Exception {
- IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
-
- assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
- assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-
- // Use TelecomManager API to answer the ringing call.
- TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
- .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
- telecomManager.acceptRingingCall();
-
- verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
- .answer(ids.mCallId);
- }
-
- /**
- * Tests the {@link TelecomManager#acceptRingingCall()} API. Tests simple case of an incoming
- * video call, which should be answered as video.
- *
- * @throws Exception
- */
- public void testTelecomManagerAcceptRingingVideoCall() throws Exception {
- IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
-
- assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
- assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-
- // Use TelecomManager API to answer the ringing call; the default expected behavior is to
- // answer using whatever video state the ringing call requests.
- TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
- .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
- telecomManager.acceptRingingCall();
-
- // Answer video API should be called
- verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
- .answerVideo(eq(ids.mCallId), eq(VideoProfile.STATE_BIDIRECTIONAL));
- }
-
- /**
- * Tests the {@link TelecomManager#acceptRingingCall(int)} API. Tests answering a video call
- * as an audio call.
- *
- * @throws Exception
- */
- public void testTelecomManagerAcceptRingingVideoCallAsAudio() throws Exception {
- IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
-
- assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
- assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-
- // Use TelecomManager API to answer the ringing call.
- TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
- .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
- telecomManager.acceptRingingCall(VideoProfile.STATE_AUDIO_ONLY);
-
- // The generic answer method on the ConnectionService is used to answer audio-only calls.
- verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
- .answer(eq(ids.mCallId));
- }
-
- /**
- * Tests the {@link TelecomManager#acceptRingingCall()} API. Tests simple case of an incoming
- * video call, where an attempt is made to answer with an invalid video state.
- *
- * @throws Exception
- */
- public void testTelecomManagerAcceptRingingInvalidVideoState() throws Exception {
- IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
-
- assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
- assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-
- // Use TelecomManager API to answer the ringing call; the default expected behavior is to
- // answer using whatever video state the ringing call requests.
- TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
- .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
- telecomManager.acceptRingingCall(999 /* invalid videostate */);
-
- // Answer video API should be called
- verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
- .answerVideo(eq(ids.mCallId), eq(VideoProfile.STATE_BIDIRECTIONAL));
- }
-
- // A simple incoming call, similar in scope to the previous test
- private IdPair startAndMakeActiveIncomingCall(
+ protected IdPair startAndMakeActiveIncomingCall(
String number,
PhoneAccountHandle phoneAccountHandle,
ConnectionServiceFixture connectionServiceFixture) throws Exception {
+ return startAndMakeActiveIncomingCall(number, phoneAccountHandle, connectionServiceFixture,
+ VideoProfile.STATE_AUDIO_ONLY);
+ }
+
+ // A simple incoming call, similar in scope to the previous test
+ protected IdPair startAndMakeActiveIncomingCall(
+ String number,
+ PhoneAccountHandle phoneAccountHandle,
+ ConnectionServiceFixture connectionServiceFixture,
+ int videoState) throws Exception {
IdPair ids = startIncomingPhoneCall(number, phoneAccountHandle, connectionServiceFixture);
assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
mInCallServiceFixtureX.mInCallAdapter
- .answerCall(ids.mCallId, VideoProfile.STATE_AUDIO_ONLY);
+ .answerCall(ids.mCallId, videoState);
- verify(connectionServiceFixture.getTestDouble())
- .answer(ids.mConnectionId);
+ if (!VideoProfile.isVideo(videoState)) {
+ verify(connectionServiceFixture.getTestDouble())
+ .answer(ids.mConnectionId);
+ } else {
+ verify(connectionServiceFixture.getTestDouble())
+ .answerVideo(ids.mConnectionId, videoState);
+ }
connectionServiceFixture.sendSetActive(ids.mConnectionId);
assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
@@ -862,236 +639,6 @@
return ids;
}
- public void testSingleIncomingCallLocalDisconnect() throws Exception {
- IdPair ids = startAndMakeActiveIncomingCall(
- "650-555-1212",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
-
- mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
- assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
- assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-
- mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
- assertEquals(Call.STATE_DISCONNECTED,
- mInCallServiceFixtureX.getCall(ids.mCallId).getState());
- assertEquals(Call.STATE_DISCONNECTED,
- mInCallServiceFixtureY.getCall(ids.mCallId).getState());
- }
-
- public void testSingleIncomingCallRemoteDisconnect() throws Exception {
- IdPair ids = startAndMakeActiveIncomingCall(
- "650-555-1212",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
-
- mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
- assertEquals(Call.STATE_DISCONNECTED,
- mInCallServiceFixtureX.getCall(ids.mCallId).getState());
- assertEquals(Call.STATE_DISCONNECTED,
- mInCallServiceFixtureY.getCall(ids.mCallId).getState());
- }
-
- public void do_testDeadlockOnOutgoingCall() throws Exception {
- final IdPair ids = startOutgoingPhoneCall(
- "650-555-1212",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA,
- Process.myUserHandle());
- rapidFire(
- new Runnable() {
- @Override
- public void run() {
- while (mCallerInfoAsyncQueryFactoryFixture.mRequests.size() > 0) {
- mCallerInfoAsyncQueryFactoryFixture.mRequests.remove(0).reply();
- }
- }
- },
- new Runnable() {
- @Override
- public void run() {
- try {
- mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
- } catch (Exception e) {
- Log.e(this, e, "");
- }
- }
- });
- }
-
- public void testDeadlockOnOutgoingCall() throws Exception {
- for (int i = 0; i < 100; i++) {
- TelecomSystemTest test = new TelecomSystemTest();
- test.setContext(getContext());
- test.setTestContext(getTestContext());
- test.setName(getName());
- test.setUp();
- test.do_testDeadlockOnOutgoingCall();
- test.tearDown();
- }
- }
-
- public void testIncomingThenOutgoingCalls() throws Exception {
- // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
- IdPair incoming = startAndMakeActiveIncomingCall(
- "650-555-2323",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
- IdPair outgoing = startAndMakeActiveOutgoingCall(
- "650-555-1212",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
- }
-
- public void testOutgoingThenIncomingCalls() throws Exception {
- // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
- IdPair outgoing = startAndMakeActiveOutgoingCall(
- "650-555-1212",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
- IdPair incoming = startAndMakeActiveIncomingCall(
- "650-555-2323",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
- verify(mConnectionServiceFixtureA.getTestDouble())
- .hold(outgoing.mConnectionId);
- mConnectionServiceFixtureA.mConnectionById.get(outgoing.mConnectionId).state =
- Connection.STATE_HOLDING;
- mConnectionServiceFixtureA.sendSetOnHold(outgoing.mConnectionId);
- assertEquals(
- Call.STATE_HOLDING,
- mInCallServiceFixtureX.getCall(outgoing.mCallId).getState());
- assertEquals(
- Call.STATE_HOLDING,
- mInCallServiceFixtureY.getCall(outgoing.mCallId).getState());
- }
-
- public void testAnalyticsSingleCall() throws Exception {
- IdPair testCall = startAndMakeActiveIncomingCall(
- "650-555-1212",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
- Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
-
- assertTrue(analyticsMap.containsKey(testCall.mCallId));
-
- Analytics.CallInfoImpl callAnalytics = analyticsMap.get(testCall.mCallId);
- assertTrue(callAnalytics.startTime > 0);
- assertEquals(0, callAnalytics.endTime);
- assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics.callDirection);
- assertFalse(callAnalytics.isInterrupted);
- assertNull(callAnalytics.callTerminationReason);
- assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
- callAnalytics.connectionService);
-
- mConnectionServiceFixtureA.
- sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR);
-
- analyticsMap = Analytics.cloneData();
- callAnalytics = analyticsMap.get(testCall.mCallId);
- assertTrue(callAnalytics.endTime > 0);
- assertNotNull(callAnalytics.callTerminationReason);
- assertEquals(DisconnectCause.ERROR, callAnalytics.callTerminationReason.getCode());
-
- StringWriter sr = new StringWriter();
- IndentingPrintWriter ip = new IndentingPrintWriter(sr, " ");
- Analytics.dump(ip);
- String dumpResult = sr.toString();
- String[] expectedFields = {"startTime", "endTime", "direction", "isAdditionalCall",
- "isInterrupted", "callTechnologies", "callTerminationReason", "connectionServices"};
- for (String field : expectedFields) {
- assertTrue(dumpResult.contains(field));
- }
- }
-
- public void testAnalyticsTwoCalls() throws Exception {
- IdPair testCall1 = startAndMakeActiveIncomingCall(
- "650-555-1212",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
- IdPair testCall2 = startAndMakeActiveOutgoingCall(
- "650-555-1213",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
-
- Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
- assertTrue(analyticsMap.containsKey(testCall1.mCallId));
- assertTrue(analyticsMap.containsKey(testCall2.mCallId));
-
- Analytics.CallInfoImpl callAnalytics1 = analyticsMap.get(testCall1.mCallId);
- Analytics.CallInfoImpl callAnalytics2 = analyticsMap.get(testCall2.mCallId);
- assertTrue(callAnalytics1.startTime > 0);
- assertTrue(callAnalytics2.startTime > 0);
- assertEquals(0, callAnalytics1.endTime);
- assertEquals(0, callAnalytics2.endTime);
-
- assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics1.callDirection);
- assertEquals(Analytics.OUTGOING_DIRECTION, callAnalytics2.callDirection);
-
- assertTrue(callAnalytics1.isInterrupted);
- assertTrue(callAnalytics2.isAdditionalCall);
-
- assertNull(callAnalytics1.callTerminationReason);
- assertNull(callAnalytics2.callTerminationReason);
-
- assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
- callAnalytics1.connectionService);
- assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
- callAnalytics1.connectionService);
-
- mConnectionServiceFixtureA.
- sendSetDisconnected(testCall2.mConnectionId, DisconnectCause.REMOTE);
- mConnectionServiceFixtureA.
- sendSetDisconnected(testCall1.mConnectionId, DisconnectCause.ERROR);
-
- analyticsMap = Analytics.cloneData();
- callAnalytics1 = analyticsMap.get(testCall1.mCallId);
- callAnalytics2 = analyticsMap.get(testCall2.mCallId);
- assertTrue(callAnalytics1.endTime > 0);
- assertTrue(callAnalytics2.endTime > 0);
- assertNotNull(callAnalytics1.callTerminationReason);
- assertNotNull(callAnalytics2.callTerminationReason);
- assertEquals(DisconnectCause.ERROR, callAnalytics1.callTerminationReason.getCode());
- assertEquals(DisconnectCause.REMOTE, callAnalytics2.callTerminationReason.getCode());
- }
-
- public void testAudioManagerOperations() throws Exception {
- AudioManager audioManager = (AudioManager) mComponentContextFixture.getTestDouble()
- .getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
-
- IdPair outgoing = startAndMakeActiveOutgoingCall(
- "650-555-1212",
- mPhoneAccountA0.getAccountHandle(),
- mConnectionServiceFixtureA);
-
- verify(audioManager, timeout(TEST_TIMEOUT))
- .requestAudioFocusForCall(anyInt(), anyInt());
- verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce())
- .setMode(AudioManager.MODE_IN_CALL);
-
- mInCallServiceFixtureX.mInCallAdapter.mute(true);
- verify(mAudioService, timeout(TEST_TIMEOUT))
- .setMicrophoneMute(eq(true), any(String.class), any(Integer.class));
- mInCallServiceFixtureX.mInCallAdapter.mute(false);
- verify(mAudioService, timeout(TEST_TIMEOUT))
- .setMicrophoneMute(eq(false), any(String.class), any(Integer.class));
-
- mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER);
- verify(audioManager, timeout(TEST_TIMEOUT))
- .setSpeakerphoneOn(true);
- mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE);
- verify(audioManager, timeout(TEST_TIMEOUT))
- .setSpeakerphoneOn(false);
-
- mConnectionServiceFixtureA.
- sendSetDisconnected(outgoing.mConnectionId, DisconnectCause.REMOTE);
-
- verify(audioManager, timeout(TEST_TIMEOUT))
- .abandonAudioFocusForCall();
- verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce())
- .setMode(AudioManager.MODE_NORMAL);
- }
-
protected static void assertTrueWithTimeout(Predicate<Void> predicate) {
int elapsed = 0;
while (elapsed < TEST_TIMEOUT) {
diff --git a/tests/src/com/android/server/telecom/tests/VideoCallTests.java b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
new file mode 100644
index 0000000..ab29c5b
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.telecom.tests;
+
+import org.mockito.ArgumentCaptor;
+
+import android.telecom.CallAudioState;
+import android.telecom.VideoProfile;
+
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+/**
+ * System tests for video-specific behavior in telecom.
+ * TODO: Add unit tests which ensure that auto-speakerphone does not occur when using a wired
+ * headset or a bluetooth headset.
+ */
+public class VideoCallTests extends TelecomSystemTest {
+
+ /**
+ * Tests to ensure an incoming video-call is automatically routed to the speakerphone when
+ * the call is answered and neither a wired headset nor bluetooth headset are connected.
+ */
+ public void testAutoSpeakerphoneIncomingBidirectional() throws Exception {
+ // Start an incoming video call.
+ IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
+ VideoProfile.STATE_BIDIRECTIONAL);
+
+ verifyAudioRoute(CallAudioState.ROUTE_SPEAKER, 3);
+ }
+
+ /**
+ * Tests to ensure an incoming receive-only video-call is answered in speakerphone mode. Note
+ * that this is not a scenario we would expect normally with the default dialer as it will
+ * always answer incoming video calls as bi-directional. It is, however, possible for a third
+ * party dialer to answer an incoming video call a a one-way video call.
+ */
+ public void testAutoSpeakerphoneIncomingReceiveOnly() throws Exception {
+ // Start an incoming video call.
+ IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
+ VideoProfile.STATE_RX_ENABLED);
+
+ verifyAudioRoute(CallAudioState.ROUTE_SPEAKER, 3);
+ }
+
+ /**
+ * Tests audio routing for an outgoing video call made with bidirectional video. Expect to be
+ * in speaker mode.
+ */
+ public void testAutoSpeakerphoneOutgoingBidirectional() throws Exception {
+ // Start an incoming video call.
+ IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
+ VideoProfile.STATE_BIDIRECTIONAL);
+
+ verifyAudioRoute(CallAudioState.ROUTE_SPEAKER, 3);
+ }
+
+ /**
+ * Tests audio routing for an outgoing video call made with transmit only video. Expect to be
+ * in speaker mode. Note: The default UI does not support making one-way video calls, but the
+ * APIs do and a third party incall UI could choose to support that.
+ */
+ public void testAutoSpeakerphoneOutgoingTransmitOnly() throws Exception {
+ // Start an incoming video call.
+ IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
+ VideoProfile.STATE_TX_ENABLED);
+
+ verifyAudioRoute(CallAudioState.ROUTE_SPEAKER, 3);
+ }
+
+ /**
+ * Tests audio routing for an outgoing video call made with transmit only video. Expect to be
+ * in speaker mode. Note: The default UI does not support making one-way video calls, but the
+ * APIs do and a third party incall UI could choose to support that.
+ */
+ public void testNoAutoSpeakerphoneOnOutgoing() throws Exception {
+ // Start an incoming video call.
+ IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
+ VideoProfile.STATE_AUDIO_ONLY);
+
+ verifyAudioRoute(CallAudioState.ROUTE_EARPIECE, 2);
+ }
+
+ /**
+ * Tests to ensure an incoming audio-only call is routed to the earpiece.
+ */
+ public void testNoAutoSpeakerphoneOnIncoming() throws Exception {
+
+ // Start an incoming video call.
+ IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
+ VideoProfile.STATE_AUDIO_ONLY);
+
+ verifyAudioRoute(CallAudioState.ROUTE_EARPIECE, 2);
+ }
+
+ /**
+ * Verifies that the
+ * {@link android.telecom.InCallService#onCallAudioStateChanged(CallAudioState)} change is
+ * called with an expected route and number of changes.
+ *
+ * @param expectedRoute The expected audio route on the latest change.
+ * @param audioStateChangeCount The number of audio state changes expected. This is set based
+ * on how many times we expect the audio route to change when
+ * setting up a call. For an audio-only call, we normally expect
+ * 2 route changes, and for a video call we expect an extra change.
+ */
+ private void verifyAudioRoute(int expectedRoute, int audioStateChangeCount) throws Exception {
+ // Capture all onCallAudioStateChanged callbacks to InCall.
+ ArgumentCaptor<CallAudioState> callAudioStateArgumentCaptor = ArgumentCaptor.forClass(
+ CallAudioState.class);
+ verify(mInCallServiceFixtureX.getTestDouble(),
+ timeout(TEST_TIMEOUT).times(audioStateChangeCount)).
+ onCallAudioStateChanged(callAudioStateArgumentCaptor.capture());
+ assertEquals(expectedRoute,
+ callAudioStateArgumentCaptor.getAllValues().get(audioStateChangeCount - 1)
+ .getRoute());
+ }
+}
diff --git a/tests/src/com/android/server/telecom/tests/VideoProviderTest.java b/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
new file mode 100644
index 0000000..d6585d9
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.telecom.tests;
+
+import com.android.server.telecom.CallAudioManager;
+import com.android.server.telecom.Log;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.internal.exceptions.ExceptionIncludingMockitoWarnings;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Camera;
+import android.graphics.SurfaceTexture;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.telecom.Call;
+import android.telecom.CallAudioState;
+import android.telecom.Connection;
+import android.telecom.Connection.VideoProvider;
+import android.telecom.InCallService;
+import android.telecom.InCallService.VideoCall;
+import android.telecom.ParcelableCall;
+import android.telecom.TelecomManager;
+import android.telecom.VideoCallImpl;
+import android.telecom.VideoProfile;
+import android.telecom.VideoProfile.CameraCapabilities;
+import android.view.Surface;
+
+import com.google.common.base.Predicate;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.RunnableFuture;
+import java.util.concurrent.TimeUnit;
+
+import static android.test.MoreAsserts.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Performs tests of the {@link VideoProvider} and {@link VideoCall} APIs. Ensures that requests
+ * sent from an InCallService are routed through Telecom to a VideoProvider, and that callbacks are
+ * correctly routed.
+ */
+public class VideoProviderTest extends TelecomSystemTest {
+ private static final int ORIENTATION_0 = 0;
+ private static final int ORIENTATION_90 = 90;
+ private static final float ZOOM_LEVEL = 3.0f;
+
+ @Mock private VideoCall.Callback mVideoCallCallback;
+ private IdPair mCallIds;
+ private InCallService.VideoCall mVideoCall;
+ private VideoCallImpl mVideoCallImpl;
+ private ConnectionServiceFixture.ConnectionInfo mConnectionInfo;
+ private CountDownLatch mVerificationLock;
+
+ private Answer mVerification = new Answer() {
+ @Override
+ public Object answer(InvocationOnMock i) {
+ mVerificationLock.countDown();
+ return null;
+ }
+ };
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ mCallIds = startAndMakeActiveOutgoingCall(
+ "650-555-1212",
+ mPhoneAccountA0.getAccountHandle(),
+ mConnectionServiceFixtureA);
+
+ // Set the video provider on the connection.
+ mConnectionServiceFixtureA.sendSetVideoProvider(
+ mConnectionServiceFixtureA.mLatestConnectionId);
+
+ // Provide a mocked VideoCall.Callback to receive callbacks via.
+ mVideoCallCallback = mock(InCallService.VideoCall.Callback.class);
+
+ mVideoCall = mInCallServiceFixtureX.getCall(mCallIds.mCallId).getVideoCallImpl();
+ mVideoCallImpl = (VideoCallImpl) mVideoCall;
+ mVideoCall.registerCallback(mVideoCallCallback);
+
+ mConnectionInfo = mConnectionServiceFixtureA.mConnectionById.get(mCallIds.mConnectionId);
+ mVerificationLock = new CountDownLatch(1);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Tests the {@link VideoCall#setCamera(String)}, {@link VideoProvider#onSetCamera(String)},
+ * and {@link VideoCall.Callback#onCameraCapabilitiesChanged(CameraCapabilities)}
+ * APIS.
+ */
+ public void testCameraChange() throws Exception {
+ // Wait until the callback has been received before performing verification.
+ doAnswer(mVerification).when(mVideoCallCallback)
+ .onCameraCapabilitiesChanged(any(CameraCapabilities.class));
+
+ // Make 2 setCamera requests.
+ mVideoCall.setCamera(MockVideoProvider.CAMERA_FRONT);
+ mVideoCall.setCamera(MockVideoProvider.CAMERA_BACK);
+
+ mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+ // Capture the video profile reported via the callback.
+ ArgumentCaptor<CameraCapabilities> cameraCapabilitiesCaptor =
+ ArgumentCaptor.forClass(CameraCapabilities.class);
+
+ // Verify that the callback was called twice and capture the callback arguments.
+ verify(mVideoCallCallback, timeout(TEST_TIMEOUT).times(2))
+ .onCameraCapabilitiesChanged(cameraCapabilitiesCaptor.capture());
+
+ assertEquals(2, cameraCapabilitiesCaptor.getAllValues().size());
+
+ List<CameraCapabilities> cameraCapabilities = cameraCapabilitiesCaptor.getAllValues();
+ // Ensure dimensions are as expected.
+ assertEquals(MockVideoProvider.CAMERA_FRONT_DIMENSIONS,
+ cameraCapabilities.get(0).getHeight());
+ assertEquals(MockVideoProvider.CAMERA_BACK_DIMENSIONS,
+ cameraCapabilities.get(1).getHeight());
+ }
+
+ /**
+ * Tests the {@link VideoCall#setPreviewSurface(Surface)} and
+ * {@link VideoProvider#onSetPreviewSurface(Surface)} APIs.
+ */
+ public void testSetPreviewSurface() throws Exception {
+ final Surface surface = new Surface(new SurfaceTexture(1));
+ mVideoCall.setPreviewSurface(surface);
+
+ assertTrueWithTimeout(new Predicate<Void>() {
+ @Override
+ public boolean apply(Void v) {
+ return mConnectionInfo.mockVideoProvider.getPreviewSurface() == surface;
+ }
+ });
+
+ mVideoCall.setPreviewSurface(null);
+
+ assertTrueWithTimeout(new Predicate<Void>() {
+ @Override
+ public boolean apply(Void v) {
+ return mConnectionInfo.mockVideoProvider.getPreviewSurface() == null;
+ }
+ });
+ }
+
+ /**
+ * Tests the {@link VideoCall#setDisplaySurface(Surface)} and
+ * {@link VideoProvider#onSetDisplaySurface(Surface)} APIs.
+ */
+ public void testSetDisplaySurface() throws Exception {
+ final Surface surface = new Surface(new SurfaceTexture(1));
+ mVideoCall.setDisplaySurface(surface);
+
+ assertTrueWithTimeout(new Predicate<Void>() {
+ @Override
+ public boolean apply(Void v) {
+ return mConnectionInfo.mockVideoProvider.getDisplaySurface() == surface;
+ }
+ });
+
+ mVideoCall.setDisplaySurface(null);
+
+ assertTrueWithTimeout(new Predicate<Void>() {
+ @Override
+ public boolean apply(Void v) {
+ return mConnectionInfo.mockVideoProvider.getDisplaySurface() == null;
+ }
+ });
+ }
+
+ /**
+ * Tests the {@link VideoCall#setDeviceOrientation(int)} and
+ * {@link VideoProvider#onSetDeviceOrientation(int)} APIs.
+ */
+ public void testSetDeviceOrientation() throws Exception {
+ mVideoCall.setDeviceOrientation(ORIENTATION_0);
+
+ assertTrueWithTimeout(new Predicate<Void>() {
+ @Override
+ public boolean apply(Void v) {
+ return mConnectionInfo.mockVideoProvider.getDeviceOrientation() == ORIENTATION_0;
+ }
+ });
+
+ mVideoCall.setDeviceOrientation(ORIENTATION_90);
+
+ assertTrueWithTimeout(new Predicate<Void>() {
+ @Override
+ public boolean apply(Void v) {
+ return mConnectionInfo.mockVideoProvider.getDeviceOrientation() == ORIENTATION_90;
+ }
+ });
+ }
+
+ /**
+ * Tests the {@link VideoCall#setZoom(float)} and {@link VideoProvider#onSetZoom(float)} APIs.
+ */
+ public void testSetZoom() throws Exception {
+ mVideoCall.setZoom(ZOOM_LEVEL);
+
+ assertTrueWithTimeout(new Predicate<Void>() {
+ @Override
+ public boolean apply(Void v) {
+ return mConnectionInfo.mockVideoProvider.getZoom() == ZOOM_LEVEL;
+ }
+ });
+ }
+
+ /**
+ * Tests the {@link VideoCall#sendSessionModifyRequest(VideoProfile)},
+ * {@link VideoProvider#onSendSessionModifyRequest(VideoProfile, VideoProfile)},
+ * {@link VideoProvider#receiveSessionModifyResponse(int, VideoProfile, VideoProfile)}, and
+ * {@link VideoCall.Callback#onSessionModifyResponseReceived(int, VideoProfile, VideoProfile)}
+ * APIs.
+ *
+ * Emulates a scenario where an InCallService sends a request to upgrade to video, which the
+ * peer accepts as-is.
+ */
+ public void testSessionModifyRequest() throws Exception {
+ VideoProfile requestProfile = new VideoProfile(VideoProfile.STATE_BIDIRECTIONAL);
+
+ // Set the starting video state on the video call impl; normally this would be set based on
+ // the original android.telecom.Call instance.
+ mVideoCallImpl.setVideoState(VideoProfile.STATE_RX_ENABLED);
+
+ doAnswer(mVerification).when(mVideoCallCallback)
+ .onSessionModifyResponseReceived(anyInt(), any(VideoProfile.class),
+ any(VideoProfile.class));
+
+ // Send the request.
+ mVideoCall.sendSessionModifyRequest(requestProfile);
+
+ mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+ // Capture the video profiles from the callback.
+ ArgumentCaptor<VideoProfile> fromVideoProfileCaptor =
+ ArgumentCaptor.forClass(VideoProfile.class);
+ ArgumentCaptor<VideoProfile> toVideoProfileCaptor =
+ ArgumentCaptor.forClass(VideoProfile.class);
+
+ // Verify we got a response and capture the profiles.
+ verify(mVideoCallCallback, timeout(TEST_TIMEOUT))
+ .onSessionModifyResponseReceived(eq(VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS),
+ fromVideoProfileCaptor.capture(), toVideoProfileCaptor.capture());
+
+ assertEquals(VideoProfile.STATE_RX_ENABLED,
+ fromVideoProfileCaptor.getValue().getVideoState());
+ assertEquals(VideoProfile.STATE_BIDIRECTIONAL,
+ toVideoProfileCaptor.getValue().getVideoState());
+ }
+
+ /**
+ * Tests the {@link VideoCall#sendSessionModifyResponse(VideoProfile)},
+ * and {@link VideoProvider#onSendSessionModifyResponse(VideoProfile)} APIs.
+ */
+ public void testSessionModifyResponse() throws Exception {
+ VideoProfile sessionModifyResponse = new VideoProfile(VideoProfile.STATE_TX_ENABLED);
+
+ mVideoCall.sendSessionModifyResponse(sessionModifyResponse);
+
+ assertTrueWithTimeout(new Predicate<Void>() {
+ @Override
+ public boolean apply(Void v) {
+ VideoProfile response = mConnectionInfo.mockVideoProvider
+ .getSessionModifyResponse();
+ return response != null && response.getVideoState() == VideoProfile.STATE_TX_ENABLED;
+ }
+ });
+ }
+
+ /**
+ * Tests the {@link VideoCall#requestCameraCapabilities()} ()},
+ * {@link VideoProvider#onRequestCameraCapabilities()} ()}, and
+ * {@link VideoCall.Callback#onCameraCapabilitiesChanged(CameraCapabilities)} APIs.
+ */
+ public void testRequestCameraCapabilities() throws Exception {
+ // Wait until the callback has been received before performing verification.
+ doAnswer(mVerification).when(mVideoCallCallback)
+ .onCameraCapabilitiesChanged(any(CameraCapabilities.class));
+
+ mVideoCall.requestCameraCapabilities();
+
+ mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+ verify(mVideoCallCallback, timeout(TEST_TIMEOUT))
+ .onCameraCapabilitiesChanged(any(CameraCapabilities.class));
+ }
+
+ /**
+ * Tests the {@link VideoCall#setPauseImage(Uri)}, and
+ * {@link VideoProvider#onSetPauseImage(Uri)} APIs.
+ */
+ public void testSetPauseImage() throws Exception {
+ final Uri testUri = Uri.fromParts("file", "test.jpg", null);
+ mVideoCall.setPauseImage(testUri);
+
+ assertTrueWithTimeout(new Predicate<Void>() {
+ @Override
+ public boolean apply(Void v) {
+ Uri pauseImage = mConnectionInfo.mockVideoProvider.getPauseImage();
+ return pauseImage != null && pauseImage.equals(testUri);
+ }
+ });
+ }
+
+ /**
+ * Tests the {@link VideoCall#requestCallDataUsage()},
+ * {@link VideoProvider#onRequestConnectionDataUsage()}, and
+ * {@link VideoCall.Callback#onCallDataUsageChanged(long)} APIs.
+ */
+ public void testRequestDataUsage() throws Exception {
+ // Wait until the callback has been received before performing verification.
+ doAnswer(mVerification).when(mVideoCallCallback)
+ .onCallDataUsageChanged(anyLong());
+
+ mVideoCall.requestCallDataUsage();
+
+ mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+ verify(mVideoCallCallback, timeout(TEST_TIMEOUT))
+ .onCallDataUsageChanged(eq(MockVideoProvider.DATA_USAGE));
+ }
+
+ /**
+ * Tests the {@link VideoProvider#receiveSessionModifyRequest(VideoProfile)},
+ * {@link VideoCall.Callback#onSessionModifyRequestReceived(VideoProfile)} APIs.
+ */
+ public void testReceiveSessionModifyRequest() throws Exception {
+ // Wait until the callback has been received before performing verification.
+ doAnswer(mVerification).when(mVideoCallCallback)
+ .onSessionModifyRequestReceived(any(VideoProfile.class));
+
+ mConnectionInfo.mockVideoProvider.sendMockSessionModifyRequest();
+
+ mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+ ArgumentCaptor<VideoProfile> requestProfileCaptor =
+ ArgumentCaptor.forClass(VideoProfile.class);
+ verify(mVideoCallCallback, timeout(TEST_TIMEOUT))
+ .onSessionModifyRequestReceived(requestProfileCaptor.capture());
+ assertEquals(VideoProfile.STATE_BIDIRECTIONAL,
+ requestProfileCaptor.getValue().getVideoState());
+ }
+
+
+ /**
+ * Tests the {@link VideoProvider#handleCallSessionEvent(int)}, and
+ * {@link VideoCall.Callback#onCallSessionEvent(int)} APIs.
+ */
+ public void testSessionEvent() throws Exception {
+ // Wait until the callback has been received before performing verification.
+ doAnswer(mVerification).when(mVideoCallCallback)
+ .onCallSessionEvent(anyInt());
+
+ mConnectionInfo.mockVideoProvider.sendMockSessionEvent(
+ VideoProvider.SESSION_EVENT_CAMERA_READY);
+
+ mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+ verify(mVideoCallCallback, timeout(TEST_TIMEOUT))
+ .onCallSessionEvent(eq(VideoProvider.SESSION_EVENT_CAMERA_READY));
+ }
+
+ /**
+ * Tests the {@link VideoProvider#changePeerDimensions(int, int)} and
+ * {@link VideoCall.Callback#onPeerDimensionsChanged(int, int)} APIs.
+ */
+ public void testPeerDimensionChange() throws Exception {
+ // Wait until the callback has been received before performing verification.
+ doAnswer(mVerification).when(mVideoCallCallback)
+ .onPeerDimensionsChanged(anyInt(), anyInt());
+
+ mConnectionInfo.mockVideoProvider.sendMockPeerDimensions(MockVideoProvider.PEER_DIMENSIONS,
+ MockVideoProvider.PEER_DIMENSIONS);
+
+ mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+ verify(mVideoCallCallback, timeout(TEST_TIMEOUT))
+ .onPeerDimensionsChanged(eq(MockVideoProvider.PEER_DIMENSIONS),
+ eq(MockVideoProvider.PEER_DIMENSIONS));
+ }
+
+ /**
+ * Tests the {@link VideoProvider#changeVideoQuality(int)} and
+ * {@link VideoCall.Callback#onVideoQualityChanged(int)} APIs.
+ */
+ public void testVideoQualityChange() throws Exception {
+ // Wait until the callback has been received before performing verification.
+ doAnswer(mVerification).when(mVideoCallCallback)
+ .onVideoQualityChanged(anyInt());
+
+ mConnectionInfo.mockVideoProvider.sendMockVideoQuality(VideoProfile.QUALITY_HIGH);
+
+ mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+ verify(mVideoCallCallback, timeout(TEST_TIMEOUT))
+ .onVideoQualityChanged(eq(VideoProfile.QUALITY_HIGH));
+ }
+}