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.TestUtils.shouldTestTelecom;
20 
21 import com.android.compatibility.common.util.ApiLevelUtil;
22 
23 import android.net.Uri;
24 import android.os.Build;
25 import android.os.Bundle;
26 import android.telecom.Connection;
27 import android.telecom.DisconnectCause;
28 import android.telecom.StatusHints;
29 import android.telecom.TelecomManager;
30 import android.test.AndroidTestCase;
31 
32 import java.util.Arrays;
33 import java.util.List;
34 import java.util.concurrent.Semaphore;
35 import java.util.concurrent.TimeUnit;
36 
37 public class ConnectionTest extends AndroidTestCase {
38 
testStateCallbacks()39     public void testStateCallbacks() {
40         if (!shouldTestTelecom(getContext())) {
41             return;
42         }
43 
44         final Semaphore lock = new Semaphore(0);
45         Connection connection = createConnection(lock);
46 
47         waitForStateChange(lock);
48         assertEquals(Connection.STATE_NEW, connection.getState());
49 
50         connection.setInitializing();
51         waitForStateChange(lock);
52         assertEquals(Connection.STATE_INITIALIZING, connection.getState());
53 
54         connection.setInitialized();
55         waitForStateChange(lock);
56         assertEquals(Connection.STATE_NEW, connection.getState());
57 
58         connection.setRinging();
59         waitForStateChange(lock);
60         assertEquals(Connection.STATE_RINGING, connection.getState());
61 
62         connection.setDialing();
63         waitForStateChange(lock);
64         assertEquals(Connection.STATE_DIALING, connection.getState());
65 
66         connection.setActive();
67         waitForStateChange(lock);
68         assertEquals(Connection.STATE_ACTIVE, connection.getState());
69 
70         connection.setOnHold();
71         waitForStateChange(lock);
72         assertEquals(Connection.STATE_HOLDING, connection.getState());
73 
74         connection.setPulling();
75         waitForStateChange(lock);
76         assertEquals(Connection.STATE_PULLING_CALL, connection.getState());
77 
78         connection.setDisconnected(
79                 new DisconnectCause(DisconnectCause.LOCAL, "Test call"));
80         waitForStateChange(lock);
81         assertEquals(Connection.STATE_DISCONNECTED, connection.getState());
82 
83         connection.setRinging();
84         waitForStateChange(lock);
85         assertEquals("Connection should not move out of STATE_DISCONNECTED.",
86                 Connection.STATE_DISCONNECTED, connection.getState());
87     }
88 
89     /**
90      * {@link UnsupportedOperationException} is only thrown in L MR1+.
91      */
testFailedState()92     public void testFailedState() {
93         if (ApiLevelUtil.isBefore(Build.VERSION_CODES.LOLLIPOP_MR1)) {
94             return;
95         }
96         Connection connection = Connection.createFailedConnection(
97                 new DisconnectCause(DisconnectCause.LOCAL, "Test call"));
98         assertEquals(Connection.STATE_DISCONNECTED, connection.getState());
99 
100         try {
101             connection.setRinging();
102         } catch (UnsupportedOperationException e) {
103             return;
104         }
105         fail("Connection should not move out of STATE_DISCONNECTED");
106     }
107 
108     /**
109      * {@link UnsupportedOperationException} is only thrown in L MR1+.
110      */
testCanceledState()111     public void testCanceledState() {
112         if (ApiLevelUtil.isBefore(Build.VERSION_CODES.LOLLIPOP_MR1)) {
113             return;
114         }
115         Connection connection = Connection.createCanceledConnection();
116         assertEquals(Connection.STATE_DISCONNECTED, connection.getState());
117 
118         try {
119             connection.setDialing();
120         } catch (UnsupportedOperationException e) {
121             return;
122         }
123         fail("Connection should not move out of STATE_DISCONNECTED");
124     }
125 
testSetAndGetCallerDisplayName()126     public void testSetAndGetCallerDisplayName() {
127         if (!shouldTestTelecom(getContext())) {
128             return;
129         }
130 
131         final Semaphore lock = new Semaphore(0);
132         Connection connection = createConnection(lock);
133         waitForStateChange(lock);
134 
135         connection.setCallerDisplayName("Test User", TelecomManager.PRESENTATION_ALLOWED);
136         assertEquals("Test User", connection.getCallerDisplayName());
137         assertEquals(TelecomManager.PRESENTATION_ALLOWED,
138                 connection.getCallerDisplayNamePresentation());
139     }
140 
testSetAndGetAddress()141     public void testSetAndGetAddress() {
142         if (!shouldTestTelecom(getContext())) {
143             return;
144         }
145 
146         final Semaphore lock = new Semaphore(0);
147         Connection connection = createConnection(lock);
148         waitForStateChange(lock);
149 
150         final Uri address = Uri.fromParts("tel", "1234567", null);
151         connection.setAddress(address, TelecomManager.PRESENTATION_UNKNOWN);
152         assertEquals(address, connection.getAddress());
153         assertEquals(TelecomManager.PRESENTATION_UNKNOWN, connection.getAddressPresentation());
154     }
155 
testSetAndGetConnectionCapabilities()156     public void testSetAndGetConnectionCapabilities() {
157         if (!shouldTestTelecom(getContext())) {
158             return;
159         }
160 
161         final Semaphore lock = new Semaphore(0);
162         Connection connection = createConnection(lock);
163         waitForStateChange(lock);
164 
165         final int capabilities = Connection.CAPABILITY_HOLD | Connection.CAPABILITY_CAN_PAUSE_VIDEO
166                 | Connection.CAPABILITY_MANAGE_CONFERENCE | Connection.CAPABILITY_RESPOND_VIA_TEXT;
167 
168         connection.setConnectionCapabilities(capabilities);
169 
170         assertEquals(capabilities, connection.getConnectionCapabilities());
171     }
172 
testSetAndGetConnectionProperties()173     public void testSetAndGetConnectionProperties() {
174         if (!shouldTestTelecom(getContext())) {
175             return;
176         }
177 
178         final Semaphore lock = new Semaphore(0);
179         Connection connection = createConnection(lock);
180         waitForStateChange(lock);
181 
182         final int properties = Connection.PROPERTY_IS_EXTERNAL_CALL;
183 
184         connection.setConnectionProperties(properties);
185 
186         assertEquals(properties, connection.getConnectionProperties());
187     }
188 
testSetAndGetDisconnectCause()189     public void testSetAndGetDisconnectCause() {
190         if (!shouldTestTelecom(getContext())) {
191             return;
192         }
193 
194         final Semaphore lock = new Semaphore(0);
195         Connection connection = createConnection(lock);
196         waitForStateChange(lock);
197         assertEquals(Connection.STATE_NEW, connection.getState());
198 
199         final DisconnectCause disconnectCause = new DisconnectCause(DisconnectCause.REJECTED,
200                 "No friends", "No friends to talk to", "No friends to talk to");
201 
202         connection.setDisconnected(disconnectCause);
203 
204         assertEquals(Connection.STATE_DISCONNECTED, connection.getState());
205         assertEquals(disconnectCause, connection.getDisconnectCause());
206     }
207 
testSetAndGetAudioModeIsVoip()208     public void testSetAndGetAudioModeIsVoip() {
209         if (!shouldTestTelecom(getContext())) {
210             return;
211         }
212 
213         final Semaphore lock = new Semaphore(0);
214         Connection connection = createConnection(lock);
215         waitForStateChange(lock);
216 
217         assertFalse(connection.getAudioModeIsVoip());
218         connection.setAudioModeIsVoip(true);
219         assertTrue(connection.getAudioModeIsVoip());
220     }
221 
testSetAndGetExtras()222     public void testSetAndGetExtras() {
223         if (!shouldTestTelecom(getContext())) {
224             return;
225         }
226 
227         final Semaphore lock = new Semaphore(0);
228         Connection connection = createConnection(lock);
229         waitForStateChange(lock);
230 
231         assertEquals(null, connection.getExtras());
232 
233         final Bundle extras = new Bundle();
234         extras.putBoolean("test-extra-key", true);
235         connection.setExtras(extras);
236 
237         final Bundle retrieved = connection.getExtras();
238         assertNotNull(retrieved);
239         assertTrue(extras.getBoolean("test-extra-key"));
240     }
241 
242     /**
243      * Basic local test of adding extra keys via {@link Connection#removeExtras(List)}.
244      *
245      * Extended end-to-end passing of extras is verified in
246      * {@link CallDetailsTest#testConnectionPutExtras()} and
247      * @link CallDetailsTest#testConnectionRemoveExtras()}.
248      */
testPutExtras()249     public void testPutExtras() {
250         if (!shouldTestTelecom(getContext())) {
251             return;
252         }
253 
254         final Semaphore lock = new Semaphore(0);
255         Connection connection = createConnection(lock);
256         waitForStateChange(lock);
257 
258         assertEquals(null, connection.getExtras());
259 
260         final Bundle extras = new Bundle();
261         extras.putBoolean("test-extra-key", true);
262         connection.putExtras(extras);
263 
264         final Bundle retrieved = connection.getExtras();
265         assertNotNull(retrieved);
266         assertTrue(extras.getBoolean("test-extra-key"));
267     }
268 
269     /**
270      * Basic local test of removing extra keys via {@link Connection#removeExtras(List)}.
271      *
272      * Extended end-to-end passing of extras is verified in
273      * {@link CallDetailsTest#testConnectionPutExtras()} and
274      * @link CallDetailsTest#testConnectionRemoveExtras()}.
275      */
testRemoveExtras()276     public void testRemoveExtras() {
277         if (!shouldTestTelecom(getContext())) {
278             return;
279         }
280 
281         final Semaphore lock = new Semaphore(0);
282         Connection connection = createConnection(lock);
283         waitForStateChange(lock);
284 
285         assertEquals(null, connection.getExtras());
286 
287         final Bundle extras = new Bundle();
288         extras.putBoolean("test-extra-key", true);
289         connection.putExtras(extras);
290         connection.removeExtras(Arrays.asList("test-extra-key"));
291 
292         final Bundle retrieved = connection.getExtras();
293         assertNotNull(retrieved);
294         assertFalse(retrieved.containsKey("test-extra-key"));
295     }
296 
297     /**
298      * Basic local test of removing extra keys via {@link Connection#removeExtras(String...)}.
299      *
300      * Extended end-to-end passing of extras is verified in
301      * {@link CallDetailsTest#testConnectionPutExtras()} and
302      * @link CallDetailsTest#testConnectionRemoveExtras()}.
303      */
testRemoveExtrasVariable()304     public void testRemoveExtrasVariable() {
305         if (!shouldTestTelecom(getContext())) {
306             return;
307         }
308 
309         final Semaphore lock = new Semaphore(0);
310         Connection connection = createConnection(lock);
311         waitForStateChange(lock);
312 
313         assertEquals(null, connection.getExtras());
314 
315         final Bundle extras = new Bundle();
316         extras.putBoolean("test-extra-key", true);
317         extras.putBoolean("test-extra-key2", true);
318         connection.putExtras(extras);
319         connection.removeExtras("test-extra-key", "test-extra-key2");
320 
321         final Bundle retrieved = connection.getExtras();
322         assertNotNull(retrieved);
323         assertFalse(retrieved.containsKey("test-extra-key"));
324         assertFalse(retrieved.containsKey("test-extra-key2"));
325     }
326 
327     /**
328      * Tests that the {@link Connection#sendConnectionEvent(String, Bundle)} method exists and can
329      * be called.
330      *
331      * Actual end-to-end tests can be found in {@link CallDetailsTest#testConnectionEvent()}.
332      */
testSendConnectionEvent()333     public void testSendConnectionEvent() {
334         if (!shouldTestTelecom(getContext())) {
335             return;
336         }
337 
338         final Semaphore lock = new Semaphore(0);
339         Connection connection = createConnection(lock);
340         waitForStateChange(lock);
341 
342         connection.sendConnectionEvent("test", null);
343     }
344 
testSetAndGetStatusHints()345     public void testSetAndGetStatusHints() {
346         if (!shouldTestTelecom(getContext())) {
347             return;
348         }
349 
350         final Semaphore lock = new Semaphore(0);
351         Connection connection = createConnection(lock);
352         waitForStateChange(lock);
353 
354         assertEquals(null, connection.getStatusHints());
355 
356         final StatusHints statusHints = new StatusHints("Test", null, null);
357         connection.setStatusHints(statusHints);
358         assertEquals(statusHints, connection.getStatusHints());
359     }
360 
testSetAndGetRingbackRequested()361     public void testSetAndGetRingbackRequested() {
362         if (!shouldTestTelecom(getContext())) {
363             return;
364         }
365 
366         final Semaphore lock = new Semaphore(0);
367         Connection connection = createConnection(lock);
368         waitForStateChange(lock);
369 
370         assertFalse(connection.isRingbackRequested());
371 
372         connection.setRingbackRequested(true);
373         assertTrue(connection.isRingbackRequested());
374     }
375 
testSetAndGetVideoProvider()376     public void testSetAndGetVideoProvider() {
377         if (!shouldTestTelecom(getContext())) {
378             return;
379         }
380 
381         final Semaphore lock = new Semaphore(0);
382         Connection connection = createConnection(lock);
383         waitForStateChange(lock);
384 
385         assertNull(connection.getVideoProvider());
386 
387         final Connection.VideoProvider videoProvider = new MockVideoProvider(null);
388         connection.setVideoProvider(videoProvider);
389         assertEquals(videoProvider, connection.getVideoProvider());
390     }
391 
testCallerNumberVerificationStatus()392     public void testCallerNumberVerificationStatus() {
393         if (!shouldTestTelecom(getContext())) {
394             return;
395         }
396 
397         final Semaphore lock = new Semaphore(0);
398         Connection connection = createConnection(lock);
399         waitForStateChange(lock);
400 
401         connection.setCallerNumberVerificationStatus(Connection.VERIFICATION_STATUS_FAILED);
402         assertEquals(Connection.VERIFICATION_STATUS_FAILED,
403                 connection.getCallerNumberVerificationStatus());
404         connection.setCallerNumberVerificationStatus(Connection.VERIFICATION_STATUS_NOT_VERIFIED);
405         assertEquals(Connection.VERIFICATION_STATUS_NOT_VERIFIED,
406                 connection.getCallerNumberVerificationStatus());
407         connection.setCallerNumberVerificationStatus(Connection.VERIFICATION_STATUS_PASSED);
408         assertEquals(Connection.VERIFICATION_STATUS_PASSED,
409                 connection.getCallerNumberVerificationStatus());
410     }
411 
testStateToString()412     public void testStateToString() {
413         if (!shouldTestTelecom(getContext())) {
414             return;
415         }
416 
417         assertEquals("INITIALIZING", Connection.stateToString(Connection.STATE_INITIALIZING));
418         assertEquals("NEW", Connection.stateToString(Connection.STATE_NEW));
419         assertEquals("RINGING", Connection.stateToString(Connection.STATE_RINGING));
420         assertEquals("DIALING", Connection.stateToString(Connection.STATE_DIALING));
421         assertEquals("ACTIVE", Connection.stateToString(Connection.STATE_ACTIVE));
422         assertEquals("HOLDING", Connection.stateToString(Connection.STATE_HOLDING));
423         assertEquals("DISCONNECTED", Connection.stateToString(Connection.STATE_DISCONNECTED));
424     }
425 
testCapabilitiesToString()426     public void testCapabilitiesToString() {
427         if (!shouldTestTelecom(getContext())) {
428             return;
429         }
430 
431         assertEquals("[Capabilities: CAPABILITY_HOLD]",
432                 Connection.capabilitiesToString(Connection.CAPABILITY_HOLD));
433         assertEquals("[Capabilities: CAPABILITY_MUTE]",
434                 Connection.capabilitiesToString(Connection.CAPABILITY_MUTE));
435         assertEquals("[Capabilities: CAPABILITY_HOLD "
436                 + "CAPABILITY_RESPOND_VIA_TEXT "
437                 + "CAPABILITY_MANAGE_CONFERENCE]",
438                 Connection.capabilitiesToString(Connection.CAPABILITY_HOLD
439                         | Connection.CAPABILITY_RESPOND_VIA_TEXT
440                         | Connection.CAPABILITY_MANAGE_CONFERENCE));
441     }
442 
443     /**
444      * Tests the {@link Connection#propertiesToString(int)} method.
445      */
testPropertiesToString()446     public void testPropertiesToString() {
447         if (!shouldTestTelecom(getContext())) {
448             return;
449         }
450 
451         assertEquals("[Properties: PROPERTY_IS_EXTERNAL_CALL]",
452                 Connection.propertiesToString(Connection.PROPERTY_IS_EXTERNAL_CALL));
453     }
454 
createConnection(final Semaphore lock)455     private static Connection createConnection(final Semaphore lock) {
456         BasicConnection connection = new BasicConnection();
457         connection.setLock(lock);
458         return connection;
459     }
460 
waitForStateChange(Semaphore lock)461     private static void waitForStateChange(Semaphore lock) {
462         try {
463             lock.tryAcquire(1000, TimeUnit.MILLISECONDS);
464         } catch (InterruptedException e) {
465             fail("State transition timed out");
466         }
467     }
468 
469     private static final class BasicConnection extends Connection {
470         private Semaphore mLock;
471 
setLock(Semaphore lock)472         public void setLock(Semaphore lock) {
473             mLock = lock;
474         }
475 
476         @Override
onStateChanged(int state)477         public void onStateChanged(int state) {
478             mLock.release();
479         }
480     }
481 }
482