Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2017 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.Call;
     21 import android.telecom.Connection;
     22 import android.telecom.TelecomManager;
     23 
     24 import java.io.IOException;
     25 
     26 public class RttOperationsTest extends BaseTelecomTestWithMockServices {
     27     private static final int RTT_SEND_TIMEOUT_MILLIS = 1000;
     28     private static final String[] TEST_STRINGS = {
     29             "A",
     30             "AB",
     31             "ABCDEFG",
     32             "",
     33             ""
     34     };
     35     private static final int RTT_FAILURE_REASON = 2;
     36 
     37     private boolean mInitialRttMode;
     38 
     39     @Override
     40     protected void setUp() throws Exception {
     41         super.setUp();
     42         if (mShouldTestTelecom) {
     43             setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
     44             mInitialRttMode = getRttMasterSwitch();
     45             setRttMasterSwitch(false);
     46         }
     47     }
     48 
     49     @Override
     50     protected void tearDown() throws Exception {
     51         super.tearDown();
     52         if (mShouldTestTelecom) {
     53             setRttMasterSwitch(mInitialRttMode);
     54         }
     55     }
     56 
     57     public void testOutgoingRttCall() throws Exception {
     58         if (!mShouldTestTelecom) {
     59             return;
     60         }
     61 
     62         placeRttCall(false);
     63         final MockConnection connection = verifyConnectionForOutgoingCall();
     64         final MockInCallService inCallService = mInCallCallbacks.getService();
     65         final Call call = inCallService.getLastCall();
     66         TestUtils.waitOnAllHandlers(getInstrumentation());
     67         verifyRttEnabled(call, connection);
     68     }
     69 
     70     public void testIncomingRttCall() throws Exception {
     71         if (!mShouldTestTelecom) {
     72             return;
     73         }
     74 
     75         setRttMasterSwitch(true);
     76         placeRttCall(true);
     77         final MockConnection connection = verifyConnectionForIncomingCall();
     78         final MockInCallService inCallService = mInCallCallbacks.getService();
     79         final Call call = inCallService.getLastCall();
     80         TestUtils.waitOnAllHandlers(getInstrumentation());
     81         verifyRttEnabled(call, connection);
     82     }
     83 
     84     public void testLocalRttUpgradeAccepted() throws Exception {
     85         if (!mShouldTestTelecom) {
     86             return;
     87         }
     88 
     89         placeAndVerifyCall();
     90         final MockConnection connection = verifyConnectionForOutgoingCall();
     91         final MockInCallService inCallService = mInCallCallbacks.getService();
     92         final Call call = inCallService.getLastCall();
     93         verifyRttDisabled(call);
     94 
     95         TestUtils.InvokeCounter startRttCounter =
     96                 connection.getInvokeCounter(MockConnection.ON_START_RTT);
     97         call.sendRttRequest();
     98         startRttCounter.waitForCount(1, TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
     99 
    100         connection.setRttTextStream((Connection.RttTextStream) startRttCounter.getArgs(0)[0]);
    101         connection.setConnectionProperties(
    102                 connection.getConnectionProperties() | Connection.PROPERTY_IS_RTT);
    103         connection.sendRttInitiationSuccess();
    104         TestUtils.waitOnAllHandlers(getInstrumentation());
    105         verifyRttEnabled(call, connection);
    106     }
    107 
    108     public void testLocalRttUpgradeRejected() throws Exception {
    109         if (!mShouldTestTelecom) {
    110             return;
    111         }
    112 
    113         placeAndVerifyCall();
    114         final MockConnection connection = verifyConnectionForOutgoingCall();
    115         final MockInCallService inCallService = mInCallCallbacks.getService();
    116         final Call call = inCallService.getLastCall();
    117         verifyRttDisabled(call);
    118 
    119         TestUtils.InvokeCounter startRttCounter =
    120                 connection.getInvokeCounter(MockConnection.ON_START_RTT);
    121         call.sendRttRequest();
    122         startRttCounter.waitForCount(1, TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
    123 
    124         connection.sendRttInitiationFailure(RTT_FAILURE_REASON);
    125         TestUtils.waitOnAllHandlers(getInstrumentation());
    126         mOnRttInitiationFailedCounter.waitForCount(1, TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
    127         assertEquals(call, mOnRttInitiationFailedCounter.getArgs(0)[0]);
    128         assertEquals(RTT_FAILURE_REASON, mOnRttInitiationFailedCounter.getArgs(0)[1]);
    129         verifyRttDisabled(call);
    130     }
    131 
    132     public void testAcceptRemoteRttUpgrade() throws Exception {
    133         if (!mShouldTestTelecom) {
    134             return;
    135         }
    136 
    137         placeAndVerifyCall();
    138         final MockConnection connection = verifyConnectionForOutgoingCall();
    139         final MockInCallService inCallService = mInCallCallbacks.getService();
    140         final Call call = inCallService.getLastCall();
    141         verifyRttDisabled(call);
    142 
    143         TestUtils.InvokeCounter rttRequestResponseCounter =
    144                 connection.getInvokeCounter(MockConnection.ON_RTT_REQUEST_RESPONSE);
    145         connection.sendRemoteRttRequest();
    146         mOnRttRequestCounter.waitForCount(1, TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
    147         int requestId = (Integer) mOnRttRequestCounter.getArgs(0)[1];
    148         call.respondToRttRequest(requestId, true /* accept */);
    149 
    150         rttRequestResponseCounter.waitForCount(1, TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
    151         TestUtils.waitOnAllHandlers(getInstrumentation());
    152         verifyRttEnabled(call, connection);
    153     }
    154 
    155     public void testRejectRemoteRttRequest() throws Exception {
    156         if (!mShouldTestTelecom) {
    157             return;
    158         }
    159 
    160         placeAndVerifyCall();
    161         final MockConnection connection = verifyConnectionForOutgoingCall();
    162         final MockInCallService inCallService = mInCallCallbacks.getService();
    163         final Call call = inCallService.getLastCall();
    164         verifyRttDisabled(call);
    165 
    166         TestUtils.InvokeCounter rttRequestResponseCounter =
    167                 connection.getInvokeCounter(MockConnection.ON_RTT_REQUEST_RESPONSE);
    168         connection.sendRemoteRttRequest();
    169         mOnRttRequestCounter.waitForCount(1, TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
    170         int requestId = (Integer) mOnRttRequestCounter.getArgs(0)[1];
    171         call.respondToRttRequest(requestId, false /* accept */);
    172 
    173         rttRequestResponseCounter.waitForCount(1, TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
    174         assertNull(rttRequestResponseCounter.getArgs(0)[0]);
    175         TestUtils.waitOnAllHandlers(getInstrumentation());
    176         verifyRttDisabled(call);
    177     }
    178 
    179     public void testLocalRttTermination() throws Exception {
    180         if (!mShouldTestTelecom) {
    181             return;
    182         }
    183 
    184         placeRttCall(false);
    185         final MockConnection connection = verifyConnectionForOutgoingCall();
    186         final MockInCallService inCallService = mInCallCallbacks.getService();
    187         final Call call = inCallService.getLastCall();
    188 
    189         // Skipping RTT verification since that's tested by another test
    190         TestUtils.InvokeCounter stopRttCounter =
    191                 connection.getInvokeCounter(MockConnection.ON_STOP_RTT);
    192         call.stopRtt();
    193         stopRttCounter.waitForCount(1, TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
    194         connection.setConnectionProperties(
    195                 connection.getConnectionProperties() & ~Connection.PROPERTY_IS_RTT);
    196         TestUtils.waitOnAllHandlers(getInstrumentation());
    197         verifyRttDisabled(call);
    198     }
    199 
    200     public void testRemoteRttTermination() throws Exception {
    201         if (!mShouldTestTelecom) {
    202             return;
    203         }
    204 
    205         placeRttCall(false);
    206         final MockConnection connection = verifyConnectionForOutgoingCall();
    207         final MockInCallService inCallService = mInCallCallbacks.getService();
    208         final Call call = inCallService.getLastCall();
    209 
    210         // Skipping RTT verification since that's tested by another test
    211         connection.sendRttSessionRemotelyTerminated();
    212         TestUtils.InvokeCounter stopRttCounter =
    213                 connection.getInvokeCounter(MockConnection.ON_STOP_RTT);
    214         call.stopRtt();
    215         stopRttCounter.waitForCount(1, TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
    216         connection.setConnectionProperties(
    217                 connection.getConnectionProperties() & ~Connection.PROPERTY_IS_RTT);
    218         TestUtils.waitOnAllHandlers(getInstrumentation());
    219         verifyRttDisabled(call);
    220     }
    221 
    222     private void verifyRttDisabled(Call call) {
    223         TestUtils.waitOnLocalMainLooper(TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
    224         assertFalse(call.isRttActive());
    225         assertNull(call.getRttCall());
    226     }
    227 
    228     private void verifyRttEnabled(Call call, MockConnection connection) {
    229         TestUtils.waitOnLocalMainLooper(TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
    230         Connection.RttTextStream connectionSideRtt = connection.getRttTextStream();
    231         Call.RttCall inCallSideRtt = call.getRttCall();
    232         assertNotNull(connectionSideRtt);
    233         assertTrue(call.isRttActive());
    234         assertNotNull(inCallSideRtt);
    235 
    236         verifyRttPipeIntegrity(inCallSideRtt, connectionSideRtt);
    237         verifyRttPipeReadBlocking(connectionSideRtt);
    238     }
    239 
    240     private void verifyRttPipeReadBlocking(Connection.RttTextStream connectionSide) {
    241         // Make sure that nothing gets read from the pipe
    242         boolean[] flag = new boolean[1];
    243         flag[0] = false;
    244         Thread t = new Thread(() -> {
    245             try {
    246                 connectionSide.read();
    247                 flag[0] = true;
    248             } catch (Exception e) {
    249                 // do nothing
    250             }
    251         });
    252         t.start();
    253         sleep(500);
    254         t.interrupt();
    255         assertFalse(flag[0]);
    256     }
    257 
    258     private void verifyRttPipeIntegrity(Call.RttCall inCallSide, Connection.RttTextStream
    259             connectionSide) {
    260         for (String s : TEST_STRINGS) {
    261             try {
    262                 inCallSide.write(s);
    263                 waitUntilConditionIsTrueOrTimeout(new Condition() {
    264                     String readSoFar = "";
    265                     @Override
    266                     public Object expected() {
    267                         return s;
    268                     }
    269 
    270                     @Override
    271                     public Object actual() {
    272                         try {
    273                             String newRead = connectionSide.readImmediately();
    274                             if (newRead != null) {
    275                                 readSoFar += newRead;
    276                             }
    277                             return readSoFar;
    278                         } catch (IOException e) {
    279                             fail("IOException while reading from connection side");
    280                             return null;
    281                         }
    282                     }
    283                 }, RTT_SEND_TIMEOUT_MILLIS, String.format("%s failed to send correctly.", s));
    284 
    285                 connectionSide.write(s);
    286                 waitUntilConditionIsTrueOrTimeout(new Condition() {
    287                     String readSoFar = "";
    288                     @Override
    289                     public Object expected() {
    290                         return s;
    291                     }
    292 
    293                     @Override
    294                     public Object actual() {
    295                         try {
    296                             String newRead = inCallSide.readImmediately();
    297                             if (newRead != null) {
    298                                 readSoFar += newRead;
    299                             }
    300                             return readSoFar;
    301                         } catch (IOException e) {
    302                             fail("IOException while reading from incall side");
    303                             return null;
    304                         }
    305                     }
    306                 }, RTT_SEND_TIMEOUT_MILLIS, String.format("%s failed to send correctly.", s));
    307             } catch (IOException e) {
    308                 fail(String.format(
    309                         "Caught IOException when verifying %s", s));
    310             }
    311 
    312         }
    313     }
    314 
    315     private void placeRttCall(boolean incoming) {
    316         Bundle extras = new Bundle();
    317         extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_RTT, true);
    318         if (incoming) {
    319             addAndVerifyNewIncomingCall(createTestNumber(), extras);
    320         } else {
    321             Bundle outgoingCallExtras = new Bundle();
    322             outgoingCallExtras.putParcelable(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
    323             placeAndVerifyCall(outgoingCallExtras);
    324         }
    325     }
    326 
    327     private void setRttMasterSwitch(boolean on) throws Exception {
    328         TestUtils.executeShellCommand(getInstrumentation(),
    329                 "settings put system rtt_calling_mode " + (on ? 1 : 0));
    330     }
    331 
    332     private boolean getRttMasterSwitch() throws Exception {
    333         try {
    334             return Integer.valueOf(TestUtils.executeShellCommand(
    335                     getInstrumentation(), "settings get system rtt_calling_mode")) == 1;
    336         } catch (NumberFormatException e) {
    337             // If the setting hasn't been set yet, assume it's off
    338             return false;
    339         }
    340     }
    341 }
    342