• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.telecom.cts;
18 
19 import static android.telecom.cts.ThirdPartyCallScreeningServiceTest.EXTRA_NETWORK_IDENTIFIED_EMERGENCY_CALL;
20 
21 import android.net.Uri;
22 import android.os.Bundle;
23 import android.telecom.Conference;
24 import android.telecom.Connection;
25 import android.telecom.ConnectionRequest;
26 import android.telecom.ConnectionService;
27 import android.telecom.DisconnectCause;
28 import android.telecom.PhoneAccountHandle;
29 import android.telecom.RemoteConference;
30 import android.telecom.RemoteConnection;
31 import android.telecom.TelecomManager;
32 import android.util.Log;
33 
34 import java.util.ArrayList;
35 import java.util.List;
36 import java.util.concurrent.Semaphore;
37 import java.util.concurrent.TimeUnit;
38 
39 /**
40  * Default implementation of a {@link CtsConnectionService}. This is used for the majority
41  * of Telecom CTS tests that simply require that a outgoing call is placed, or incoming call is
42  * received.
43  */
44 public class MockConnectionService extends ConnectionService {
45     public static final Uri VERSTAT_NOT_VERIFIED_NUMBER = Uri.fromParts("tel", "777", null);
46     public static final Uri VERSTAT_PASSED_NUMBER = Uri.fromParts("tel", "555", null);
47     public static final Uri VERSTAT_FAILED_NUMBER = Uri.fromParts("tel", "333", null);
48     public static final String EXTRA_TEST = "com.android.telecom.extra.TEST";
49     public static final String TEST_VALUE = "we've got it";
50     public static final int CONNECTION_PRESENTATION =  TelecomManager.PRESENTATION_ALLOWED;
51 
52     public static final int EVENT_CONNECTION_SERVICE_FOCUS_GAINED = 0;
53     public static final int EVENT_CONNECTION_SERVICE_FOCUS_LOST = 1;
54     public static final int EVENT_CONNECTION_SERVICE_CREATE_CONNECTION = 2;
55     public static final int EVENT_CONNECTION_SERVICE_CREATE_CONNECTION_FAILED = 3;
56     // Update TOTAL_EVENT below with last event.
57     private static final int TOTAL_EVENT = EVENT_CONNECTION_SERVICE_CREATE_CONNECTION_FAILED + 1;
58 
59     private static final int DEFAULT_EVENT_TIMEOUT_MS = 2000;
60 
61     private final Semaphore[] mEventLock = initializeSemaphore(TOTAL_EVENT);
62 
63     /**
64      * Used to control whether the {@link MockVideoProvider} will be created when connections are
65      * created.  Used by {@link VideoCallTest#testVideoCallDelayProvider()} to test scenario where
66      * the {@link MockVideoProvider} is not created immediately when the Connection is created.
67      */
68     private boolean mCreateVideoProvider = true;
69 
70     public Semaphore lock = new Semaphore(0);
71     public List<MockConnection> outgoingConnections = new ArrayList<MockConnection>();
72     public List<MockConnection> incomingConnections = new ArrayList<MockConnection>();
73     public List<RemoteConnection> remoteConnections = new ArrayList<RemoteConnection>();
74     public List<MockConference> conferences = new ArrayList<MockConference>();
75     public List<RemoteConference> remoteConferences = new ArrayList<RemoteConference>();
76     public List<MockConnection> failedConnections = new ArrayList<>();
77     public ConnectionRequest connectionRequest = null;
78 
79     @Override
onCreateOutgoingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)80     public Connection onCreateOutgoingConnection(PhoneAccountHandle connectionManagerPhoneAccount,
81             ConnectionRequest request) {
82         final MockConnection connection = new MockConnection();
83         connection.setAddress(request.getAddress(), CONNECTION_PRESENTATION);
84         connection.setMockPhoneAccountHandle(connectionManagerPhoneAccount);
85         connection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORT_HOLD |
86                 Connection.CAPABILITY_HOLD
87                 | Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL
88                 | Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
89         if (mCreateVideoProvider) {
90             connection.createMockVideoProvider();
91         } else {
92             mCreateVideoProvider = true;
93         }
94         connection.setVideoState(request.getVideoState());
95         connection.setInitializing();
96         if (request.isRequestingRtt()) {
97             connection.setRttTextStream(request.getRttTextStream());
98             connection.setConnectionProperties(connection.getConnectionProperties() |
99                     Connection.PROPERTY_IS_RTT);
100         }
101         Bundle testExtra;
102         if (request.getExtras() != null) {
103             testExtra = request.getExtras();
104         } else {
105             testExtra = new Bundle();
106         }
107         // Emit an extra into the connection.  We'll see if it makes it through.
108         testExtra.putString(EXTRA_TEST, TEST_VALUE);
109         connection.putExtras(testExtra);
110         outgoingConnections.add(connection);
111         lock.release();
112         mEventLock[EVENT_CONNECTION_SERVICE_CREATE_CONNECTION].release();
113         return connection;
114     }
115 
116     @Override
onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)117     public Connection onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount,
118             ConnectionRequest request) {
119         final MockConnection connection = new MockConnection();
120         connection.setAddress(request.getAddress(), CONNECTION_PRESENTATION);
121         connection.setConnectionCapabilities(connection.getConnectionCapabilities()
122                 | Connection.CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION
123                 | Connection.CAPABILITY_SUPPORT_HOLD
124                 | Connection.CAPABILITY_HOLD);
125         connection.createMockVideoProvider();
126         ((Connection) connection).setVideoState(request.getVideoState());
127         if (request.isRequestingRtt()) {
128             connection.setRttTextStream(request.getRttTextStream());
129             connection.setConnectionProperties(connection.getConnectionProperties() |
130                     Connection.PROPERTY_IS_RTT);
131         }
132         connection.setRinging();
133         // Emit an extra into the connection.  We'll see if it makes it through.
134         Bundle testExtra = new Bundle();
135         testExtra.putString(EXTRA_TEST, TEST_VALUE);
136         connection.putExtras(testExtra);
137         if (VERSTAT_NOT_VERIFIED_NUMBER.equals(request.getAddress())) {
138             connection.setCallerNumberVerificationStatus(
139                     Connection.VERIFICATION_STATUS_NOT_VERIFIED);
140         } else if (VERSTAT_PASSED_NUMBER.equals(request.getAddress())) {
141             connection.setCallerNumberVerificationStatus(
142                     Connection.VERIFICATION_STATUS_PASSED);
143         } else if (VERSTAT_FAILED_NUMBER.equals(request.getAddress())) {
144             connection.setCallerNumberVerificationStatus(
145                     Connection.VERIFICATION_STATUS_FAILED);
146         }
147 
148         Bundle requestExtra = request.getExtras();
149         if (requestExtra.getBoolean(EXTRA_NETWORK_IDENTIFIED_EMERGENCY_CALL, false)) {
150             connection.setConnectionProperties(
151                     Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL);
152         }
153         incomingConnections.add(connection);
154         lock.release();
155         mEventLock[EVENT_CONNECTION_SERVICE_CREATE_CONNECTION].release();
156         return connection;
157     }
158 
159     @Override
onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)160     public void onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount,
161             ConnectionRequest request) {
162         final MockConnection connection = new MockConnection();
163         connection.setAddress(request.getAddress(), CONNECTION_PRESENTATION);
164         connection.setPhoneAccountHandle(connectionManagerPhoneAccount);
165         failedConnections.add(connection);
166         lock.release();
167         mEventLock[EVENT_CONNECTION_SERVICE_CREATE_CONNECTION_FAILED].release();
168     }
169 
170     @Override
onConference(Connection connection1, Connection connection2)171     public void onConference(Connection connection1, Connection connection2) {
172         // Make sure that these connections are already not conferenced.
173         if (connection1.getConference() == null && connection2.getConference() == null) {
174             MockConference conference = new MockConference(
175                     (MockConnection)connection1, (MockConnection)connection2);
176             CtsConnectionService.addConferenceToTelecom(conference);
177             conferences.add(conference);
178 
179             if (connection1.getState() == Connection.STATE_HOLDING){
180                 connection1.setActive();
181             }
182             if(connection2.getState() == Connection.STATE_HOLDING){
183                 connection2.setActive();
184             }
185 
186             lock.release();
187         }
188     }
189     @Override
onCreateOutgoingConference(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)190     public Conference onCreateOutgoingConference(PhoneAccountHandle connectionManagerPhoneAccount,
191             ConnectionRequest request) {
192         final Connection connection = onCreateOutgoingConnection(connectionManagerPhoneAccount,
193                 request);
194         final MockConference conference = new MockConference(connectionManagerPhoneAccount);
195         conference.addConnection(connection);
196         conferences.add(conference);
197         connectionRequest = request;
198         lock.release();
199         return conference;
200     }
201 
202     @Override
onCreateOutgoingConferenceFailed(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)203     public void onCreateOutgoingConferenceFailed(PhoneAccountHandle connectionManagerPhoneAccount,
204             ConnectionRequest request) {
205         final MockConference conference = new MockConference(connectionManagerPhoneAccount);
206         conference.setDisconnected(new DisconnectCause(DisconnectCause.CANCELED));
207         conferences.add(conference);
208         connectionRequest = request;
209         lock.release(2);
210     }
211 
212     @Override
onCreateIncomingConference(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)213     public Conference onCreateIncomingConference(PhoneAccountHandle connectionManagerPhoneAccount,
214             ConnectionRequest request) {
215         final Connection connection = onCreateIncomingConnection(connectionManagerPhoneAccount,
216                 request);
217         final MockConference conference = new MockConference(connectionManagerPhoneAccount);
218         conference.addConnection(connection);
219         connectionRequest = request;
220         conferences.add(conference);
221         lock.release();
222         return conference;
223     }
224 
225     @Override
onCreateIncomingConferenceFailed(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)226     public void onCreateIncomingConferenceFailed(PhoneAccountHandle connectionManagerPhoneAccount,
227             ConnectionRequest request) {
228         final MockConference conference = new MockConference(connectionManagerPhoneAccount);
229         conference.setDisconnected(new DisconnectCause(DisconnectCause.CANCELED));
230         conferences.add(conference);
231         connectionRequest = request;
232         lock.release(2);
233     }
234 
235     @Override
onRemoteExistingConnectionAdded(RemoteConnection connection)236     public void onRemoteExistingConnectionAdded(RemoteConnection connection) {
237         // Keep track of the remote connections added to the service
238         remoteConnections.add(connection);
239     }
240 
241     @Override
onRemoteConferenceAdded(RemoteConference conference)242     public void onRemoteConferenceAdded(RemoteConference conference) {
243         // Keep track of the remote connections added to the service
244         remoteConferences.add(conference);
245     }
246 
247     @Override
onConnectionServiceFocusGained()248     public void onConnectionServiceFocusGained() {
249         mEventLock[EVENT_CONNECTION_SERVICE_FOCUS_GAINED].release();
250     }
251 
252     @Override
onConnectionServiceFocusLost()253     public void onConnectionServiceFocusLost() {
254         mEventLock[EVENT_CONNECTION_SERVICE_FOCUS_LOST].release();
255         connectionServiceFocusReleased();
256     }
257 
setCreateVideoProvider(boolean createVideoProvider)258     public void setCreateVideoProvider(boolean createVideoProvider) {
259         mCreateVideoProvider = createVideoProvider;
260     }
261 
262     /** Returns true if the given {@code event} is happened before the default timeout. */
waitForEvent(int event)263     public boolean waitForEvent(int event) {
264         if (event < 0 || event >= mEventLock.length) {
265             return false;
266         }
267 
268         try {
269             return mEventLock[event].tryAcquire(DEFAULT_EVENT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
270         } catch (InterruptedException e) {
271             // No interaction for the given event within the given timeout.
272             return false;
273         }
274     }
275 
initializeSemaphore(int total)276     private static final Semaphore[] initializeSemaphore(int total) {
277         Semaphore[] locks = new Semaphore[total];
278         for (int i = 0; i < total; i++) {
279             locks[i] = new Semaphore(0);
280         }
281         return locks;
282     }
283 }
284