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 android.content.ContentResolver; 22 import android.telecom.cts.MockCallScreeningService.CallScreeningServiceCallbacks; 23 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.net.Uri; 27 import android.os.Bundle; 28 import android.telecom.Call; 29 import android.telecom.CallScreeningService; 30 import android.telecom.Connection; 31 import android.telecom.PhoneAccount; 32 import android.telecom.PhoneAccountHandle; 33 import android.telecom.TelecomManager; 34 import android.test.InstrumentationTestCase; 35 import android.text.TextUtils; 36 37 import java.util.concurrent.TimeUnit; 38 39 /** 40 * Verify that call screening service gets a chance to block calls. 41 */ 42 public class CallScreeningServiceTest extends InstrumentationTestCase { 43 private static final Uri TEST_NUMBER = Uri.fromParts("tel", "7", null); 44 45 public static final PhoneAccountHandle TEST_PHONE_ACCOUNT_HANDLE = new PhoneAccountHandle( 46 new ComponentName(TestUtils.PACKAGE, TestUtils.COMPONENT), 47 TestUtils.ACCOUNT_ID_1); 48 49 public static final PhoneAccount TEST_PHONE_ACCOUNT = PhoneAccount.builder( 50 TEST_PHONE_ACCOUNT_HANDLE, TestUtils.ACCOUNT_LABEL) 51 .setAddress(Uri.parse("tel:555-TEST")) 52 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER | 53 PhoneAccount.CAPABILITY_CONNECTION_MANAGER) 54 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 55 .build(); 56 57 private Context mContext; 58 private TelecomManager mTelecomManager; 59 private String mPreviousDefaultDialer; 60 MockConnectionService mConnectionService; 61 private boolean mCallFound; 62 private ContentResolver mContentResolver; 63 private int mCallerNumberVerificationStatus; 64 65 @Override setUp()66 protected void setUp() throws Exception { 67 super.setUp(); 68 mContext = getInstrumentation().getContext(); 69 mTelecomManager = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); 70 if (shouldTestTelecom(mContext)) { 71 mPreviousDefaultDialer = TestUtils.getDefaultDialer(getInstrumentation()); 72 TestUtils.setDefaultDialer(getInstrumentation(), TestUtils.PACKAGE); 73 setupConnectionService(); 74 MockCallScreeningService.enableService(mContext); 75 } 76 mContentResolver = getInstrumentation().getTargetContext().getContentResolver(); 77 } 78 79 @Override tearDown()80 protected void tearDown() throws Exception { 81 if (!TextUtils.isEmpty(mPreviousDefaultDialer)) { 82 TestUtils.setDefaultDialer(getInstrumentation(), mPreviousDefaultDialer); 83 mTelecomManager.unregisterPhoneAccount(TEST_PHONE_ACCOUNT_HANDLE); 84 CtsConnectionService.tearDown(); 85 mConnectionService = null; 86 MockCallScreeningService.disableService(mContext); 87 } 88 super.tearDown(); 89 } 90 91 /** 92 * Tests that when sending a CALL intent via the Telecom stack, Telecom binds to the registered 93 * {@link CallScreeningService}s and invokes onScreenCall. 94 */ testTelephonyCall_bindsToCallScreeningService()95 public void testTelephonyCall_bindsToCallScreeningService() { 96 if (!shouldTestTelecom(mContext)) { 97 return; 98 } 99 100 CallScreeningServiceCallbacks callbacks = createCallbacks(); 101 MockCallScreeningService.setCallbacks(callbacks); 102 addNewIncomingCall(TEST_NUMBER); 103 104 try { 105 if (callbacks.lock.tryAcquire(TestUtils.WAIT_FOR_CALL_ADDED_TIMEOUT_S, 106 TimeUnit.SECONDS)) { 107 assertTrue(mCallFound); 108 return; 109 } 110 } catch (InterruptedException e) { 111 } 112 113 fail("No call added to CallScreeningService."); 114 } 115 116 /** 117 * Tests that when sendinga a CALL intent via the Telecom stack and the test number is in the 118 * user's contact, Telecom binds to the registered {@link CallScreeningService}s and invokes 119 * onScreenCall. 120 */ testBindsToCallScreeningServiceWhenContactExist()121 public void testBindsToCallScreeningServiceWhenContactExist() throws Exception { 122 if (!shouldTestTelecom(mContext)) { 123 return; 124 } 125 126 CallScreeningServiceCallbacks callbacks = createCallbacks(); 127 MockCallScreeningService.setCallbacks(callbacks); 128 Uri contactUri = TestUtils.insertContact(mContentResolver, 129 TEST_NUMBER.getSchemeSpecificPart()); 130 addNewIncomingCall(TEST_NUMBER); 131 132 try { 133 if (callbacks.lock.tryAcquire(TestUtils.WAIT_FOR_CALL_ADDED_TIMEOUT_S, 134 TimeUnit.SECONDS)) { 135 assertTrue(mCallFound); 136 137 return; 138 } 139 } catch (InterruptedException e) { 140 } finally { 141 assertEquals(1, TestUtils.deleteContact(mContentResolver, contactUri)); 142 } 143 144 fail("No call added to CallScreeningService."); 145 } 146 147 /** 148 * Tests passing of number verification status. 149 */ testVerificationFailed()150 public void testVerificationFailed() { 151 if (!shouldTestTelecom(mContext)) { 152 return; 153 } 154 155 CallScreeningServiceCallbacks callbacks = createCallbacks(); 156 MockCallScreeningService.setCallbacks(callbacks); 157 addNewIncomingCall(MockConnectionService.VERSTAT_FAILED_NUMBER); 158 159 try { 160 if (callbacks.lock.tryAcquire(TestUtils.WAIT_FOR_CALL_ADDED_TIMEOUT_S, 161 TimeUnit.SECONDS)) { 162 assertTrue(mCallFound); 163 assertEquals(Connection.VERIFICATION_STATUS_FAILED, 164 mCallerNumberVerificationStatus); 165 return; 166 } 167 } catch (InterruptedException e) { 168 } 169 } 170 171 /** 172 * Tests passing of number verification status. 173 */ testNumberNotVerified()174 public void testNumberNotVerified() { 175 if (!shouldTestTelecom(mContext)) { 176 return; 177 } 178 179 CallScreeningServiceCallbacks callbacks = createCallbacks(); 180 MockCallScreeningService.setCallbacks(callbacks); 181 addNewIncomingCall(MockConnectionService.VERSTAT_NOT_VERIFIED_NUMBER); 182 183 try { 184 if (callbacks.lock.tryAcquire(TestUtils.WAIT_FOR_CALL_ADDED_TIMEOUT_S, 185 TimeUnit.SECONDS)) { 186 assertTrue(mCallFound); 187 assertEquals(Connection.VERIFICATION_STATUS_NOT_VERIFIED, 188 mCallerNumberVerificationStatus); 189 return; 190 } 191 } catch (InterruptedException e) { 192 } 193 194 fail("No call added to CallScreeningService."); 195 } 196 addNewIncomingCall(Uri incomingHandle)197 private void addNewIncomingCall(Uri incomingHandle) { 198 Bundle extras = new Bundle(); 199 extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, incomingHandle); 200 mTelecomManager.addNewIncomingCall(TEST_PHONE_ACCOUNT_HANDLE, extras); 201 } 202 createCallbacks()203 private CallScreeningServiceCallbacks createCallbacks() { 204 return new CallScreeningServiceCallbacks() { 205 @Override 206 public void onScreenCall(Call.Details callDetails) { 207 mCallFound = true; 208 mCallerNumberVerificationStatus = callDetails.getCallerNumberVerificationStatus(); 209 CallScreeningService.CallResponse response = 210 new CallScreeningService.CallResponse.Builder() 211 .setDisallowCall(true) 212 .setRejectCall(true) 213 .setSilenceCall(false) 214 .setSkipCallLog(true) 215 .setSkipNotification(true) 216 .build(); 217 getService().respondToCall(callDetails, response); 218 lock.release(); 219 } 220 }; 221 } 222 223 private void setupConnectionService() throws Exception { 224 mConnectionService = new MockConnectionService(); 225 CtsConnectionService.setUp(mConnectionService); 226 227 mTelecomManager.registerPhoneAccount(TEST_PHONE_ACCOUNT); 228 TestUtils.enablePhoneAccount(getInstrumentation(), TEST_PHONE_ACCOUNT_HANDLE); 229 // Wait till the adb commands have executed and account is enabled in Telecom database. 230 assertPhoneAccountEnabled(TEST_PHONE_ACCOUNT_HANDLE); 231 } 232 233 private void assertPhoneAccountEnabled(final PhoneAccountHandle handle) { 234 waitUntilConditionIsTrueOrTimeout( 235 new Condition() { 236 @Override 237 public Object expected() { 238 return true; 239 } 240 241 @Override 242 public Object actual() { 243 PhoneAccount phoneAccount = mTelecomManager.getPhoneAccount(handle); 244 return (phoneAccount != null && phoneAccount.isEnabled()); 245 } 246 }, 247 TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS, 248 "Phone account enable failed for " + handle 249 ); 250 } 251 252 private void waitUntilConditionIsTrueOrTimeout(Condition condition, long timeout, 253 String description) { 254 final long start = System.currentTimeMillis(); 255 while (!condition.expected().equals(condition.actual()) 256 && System.currentTimeMillis() - start < timeout) { 257 sleep(50); 258 } 259 assertEquals(description, condition.expected(), condition.actual()); 260 } 261 262 private void sleep(long ms) { 263 try { 264 Thread.sleep(ms); 265 } catch (InterruptedException e) { 266 } 267 } 268 269 protected interface Condition { 270 Object expected(); 271 Object actual(); 272 } 273 } 274