1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.telecom.cts; 18 19 import android.os.Bundle; 20 import android.telecom.Connection; 21 import android.telecom.ConnectionRequest; 22 import android.telecom.ConnectionService; 23 import android.telecom.PhoneAccountHandle; 24 import android.telecom.RemoteConference; 25 import android.telecom.RemoteConnection; 26 import android.telecom.TelecomManager; 27 28 import java.util.ArrayList; 29 import java.util.List; 30 import java.util.concurrent.Semaphore; 31 import java.util.concurrent.TimeUnit; 32 33 /** 34 * Default implementation of a {@link CtsConnectionService}. This is used for the majority 35 * of Telecom CTS tests that simply require that a outgoing call is placed, or incoming call is 36 * received. 37 */ 38 public class MockConnectionService extends ConnectionService { 39 public static final String EXTRA_TEST = "com.android.telecom.extra.TEST"; 40 public static final String TEST_VALUE = "we've got it"; 41 public static final int CONNECTION_PRESENTATION = TelecomManager.PRESENTATION_ALLOWED; 42 43 public static final int EVENT_CONNECTION_SERVICE_FOCUS_GAINED = 0; 44 public static final int EVENT_CONNECTION_SERVICE_FOCUS_LOST = 1; 45 46 // Next event id is 2 47 private static final int TOTAL_EVENT = EVENT_CONNECTION_SERVICE_FOCUS_LOST + 1; 48 49 private static final int DEFAULT_EVENT_TIMEOUT_MS = 2000; 50 51 private final Semaphore[] mEventLock = initializeSemaphore(TOTAL_EVENT); 52 53 /** 54 * Used to control whether the {@link MockVideoProvider} will be created when connections are 55 * created. Used by {@link VideoCallTest#testVideoCallDelayProvider()} to test scenario where 56 * the {@link MockVideoProvider} is not created immediately when the Connection is created. 57 */ 58 private boolean mCreateVideoProvider = true; 59 60 public Semaphore lock = new Semaphore(0); 61 public List<MockConnection> outgoingConnections = new ArrayList<MockConnection>(); 62 public List<MockConnection> incomingConnections = new ArrayList<MockConnection>(); 63 public List<RemoteConnection> remoteConnections = new ArrayList<RemoteConnection>(); 64 public List<MockConference> conferences = new ArrayList<MockConference>(); 65 public List<RemoteConference> remoteConferences = new ArrayList<RemoteConference>(); 66 67 @Override onCreateOutgoingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)68 public Connection onCreateOutgoingConnection(PhoneAccountHandle connectionManagerPhoneAccount, 69 ConnectionRequest request) { 70 final MockConnection connection = new MockConnection(); 71 connection.setAddress(request.getAddress(), CONNECTION_PRESENTATION); 72 connection.setPhoneAccountHandle(connectionManagerPhoneAccount); 73 connection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORT_HOLD | 74 Connection.CAPABILITY_HOLD 75 | Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL 76 | Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL); 77 if (mCreateVideoProvider) { 78 connection.createMockVideoProvider(); 79 } else { 80 mCreateVideoProvider = true; 81 } 82 connection.setVideoState(request.getVideoState()); 83 connection.setInitializing(); 84 if (request.isRequestingRtt()) { 85 connection.setRttTextStream(request.getRttTextStream()); 86 connection.setConnectionProperties(connection.getConnectionProperties() | 87 Connection.PROPERTY_IS_RTT); 88 } 89 // Emit an extra into the connection. We'll see if it makes it through. 90 Bundle testExtra = new Bundle(); 91 testExtra.putString(EXTRA_TEST, TEST_VALUE); 92 connection.putExtras(testExtra); 93 outgoingConnections.add(connection); 94 lock.release(); 95 return connection; 96 } 97 98 @Override onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)99 public Connection onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount, 100 ConnectionRequest request) { 101 final MockConnection connection = new MockConnection(); 102 connection.setAddress(request.getAddress(), CONNECTION_PRESENTATION); 103 connection.setConnectionCapabilities(connection.getConnectionCapabilities() 104 | Connection.CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION 105 | Connection.CAPABILITY_SUPPORT_HOLD 106 | Connection.CAPABILITY_HOLD); 107 connection.createMockVideoProvider(); 108 ((Connection) connection).setVideoState(request.getVideoState()); 109 if (request.isRequestingRtt()) { 110 connection.setRttTextStream(request.getRttTextStream()); 111 connection.setConnectionProperties(connection.getConnectionProperties() | 112 Connection.PROPERTY_IS_RTT); 113 } 114 connection.setRinging(); 115 // Emit an extra into the connection. We'll see if it makes it through. 116 Bundle testExtra = new Bundle(); 117 testExtra.putString(EXTRA_TEST, TEST_VALUE); 118 connection.putExtras(testExtra); 119 120 incomingConnections.add(connection); 121 lock.release(); 122 return connection; 123 } 124 125 @Override onConference(Connection connection1, Connection connection2)126 public void onConference(Connection connection1, Connection connection2) { 127 // Make sure that these connections are already not conferenced. 128 if (connection1.getConference() == null && connection2.getConference() == null) { 129 MockConference conference = new MockConference( 130 (MockConnection)connection1, (MockConnection)connection2); 131 CtsConnectionService.addConferenceToTelecom(conference); 132 conferences.add(conference); 133 134 if (connection1.getState() == Connection.STATE_HOLDING){ 135 connection1.setActive(); 136 } 137 if(connection2.getState() == Connection.STATE_HOLDING){ 138 connection2.setActive(); 139 } 140 141 lock.release(); 142 } 143 } 144 145 @Override onRemoteExistingConnectionAdded(RemoteConnection connection)146 public void onRemoteExistingConnectionAdded(RemoteConnection connection) { 147 // Keep track of the remote connections added to the service 148 remoteConnections.add(connection); 149 } 150 151 @Override onRemoteConferenceAdded(RemoteConference conference)152 public void onRemoteConferenceAdded(RemoteConference conference) { 153 // Keep track of the remote connections added to the service 154 remoteConferences.add(conference); 155 } 156 157 @Override onConnectionServiceFocusGained()158 public void onConnectionServiceFocusGained() { 159 mEventLock[EVENT_CONNECTION_SERVICE_FOCUS_GAINED].release(); 160 } 161 162 @Override onConnectionServiceFocusLost()163 public void onConnectionServiceFocusLost() { 164 mEventLock[EVENT_CONNECTION_SERVICE_FOCUS_LOST].release(); 165 connectionServiceFocusReleased(); 166 } 167 setCreateVideoProvider(boolean createVideoProvider)168 public void setCreateVideoProvider(boolean createVideoProvider) { 169 mCreateVideoProvider = createVideoProvider; 170 } 171 172 /** Returns true if the given {@code event} is happened before the default timeout. */ waitForEvent(int event)173 public boolean waitForEvent(int event) { 174 if (event < 0 || event >= mEventLock.length) { 175 return false; 176 } 177 178 try { 179 return mEventLock[event].tryAcquire(DEFAULT_EVENT_TIMEOUT_MS, TimeUnit.MILLISECONDS); 180 } catch (InterruptedException e) { 181 // No interaction for the given event within the given timeout. 182 return false; 183 } 184 } 185 initializeSemaphore(int total)186 private static final Semaphore[] initializeSemaphore(int total) { 187 Semaphore[] locks = new Semaphore[total]; 188 for (int i = 0; i < total; i++) { 189 locks[i] = new Semaphore(0); 190 } 191 return locks; 192 } 193 } 194