1 /* 2 * Copyright (C) 2016 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 com.android.cts.numberblocking.hostside; 18 19 import com.android.cts.migration.MigrationHelper; 20 import com.android.ddmlib.Log; 21 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner; 22 import com.android.tradefed.build.IBuildInfo; 23 import com.android.tradefed.device.DeviceNotAvailableException; 24 import com.android.tradefed.log.LogUtil; 25 import com.android.tradefed.result.CollectingTestListener; 26 import com.android.tradefed.testtype.DeviceTestCase; 27 import com.android.tradefed.testtype.IBuildReceiver; 28 29 import java.io.File; 30 31 /** 32 * Multi-user tests for number blocking. 33 */ 34 // To run the tests in this file w/o running all the cts tests: 35 // make cts 36 // cts-tradefed 37 // run cts -m CtsHostsideNumberBlockingTestCases 38 public class NumberBlockingTest extends DeviceTestCase implements IBuildReceiver { 39 private static final String BLOCKED_NUMBER = "556"; 40 private static final String PHONE_ACCOUNT_ID = "test_call_provider_id"; 41 private static final String TEST_APK = "CtsHostsideNumberBlockingAppTest.apk"; 42 private static final String NUMBER_BLOCKING_TESTS_PKG = 43 NumberBlockingTest.class.getPackage().getName(); 44 private static final String CALL_BLOCKING_TEST_CLASS_NAME = "CallBlockingTest"; 45 private static final String NUMBER_BLOCKING_APP_TEST_CLASS_NAME = "NumberBlockingAppTest"; 46 private static final String TEST_APP_CONNECTION_SERVICE_NAME = "DummyConnectionService"; 47 private static final String SECONDARY_USER_NAME = "NumberBlockingTest SecondaryUser"; 48 private static final String FEATURE_TELEPHONY = "android.hardware.telephony"; 49 private static final String FEATURE_CONNECTION_SERVICE = "android.software.connectionservice"; 50 51 private int mSecondaryUserId; 52 private int mPrimaryUserSerialNumber; 53 private int mSecondaryUserSerialNumber; 54 55 private IBuildInfo mCtsBuild; 56 private boolean mHasFeature; 57 58 @Override setUp()59 protected void setUp() throws Exception { 60 super.setUp(); 61 62 mHasFeature = getDevice().isMultiUserSupported() 63 && getDevice().hasFeature(FEATURE_TELEPHONY) 64 && getDevice().hasFeature(FEATURE_CONNECTION_SERVICE); 65 66 if (!mHasFeature) { 67 return; 68 } 69 70 installTestAppForUser(getDevice().getPrimaryUserId()); 71 createSecondaryUser(); 72 installTestAppForUser(mSecondaryUserId); 73 74 mPrimaryUserSerialNumber = getUserSerialNumber(getDevice().getPrimaryUserId()); 75 mSecondaryUserSerialNumber = getUserSerialNumber(mSecondaryUserId); 76 } 77 78 @Override tearDown()79 protected void tearDown() throws Exception { 80 if (mHasFeature) { 81 getDevice().removeUser(mSecondaryUserId); 82 } 83 84 super.tearDown(); 85 } 86 87 @Override setBuild(IBuildInfo iBuildInfo)88 public void setBuild(IBuildInfo iBuildInfo) { 89 mCtsBuild = iBuildInfo; 90 } 91 testNumberBlocking()92 public void testNumberBlocking() throws Exception { 93 if (!mHasFeature) { 94 LogUtil.CLog.logAndDisplay(Log.LogLevel.INFO, 95 "Skipping number blocking test as the feature is not supported."); 96 return; 97 } 98 99 try { 100 // First run tests for primary user. 101 // Cleanup state prior to running tests. 102 setTestAppAsDefaultSmsAppForUser( 103 true /* setToSmsApp */, getDevice().getPrimaryUserId()); 104 runTestAsPrimaryUser(NUMBER_BLOCKING_APP_TEST_CLASS_NAME, 105 "testCleanupBlockedNumberAsPrimaryUserSucceeds"); 106 107 // Block a number as a privileged app that can block numbers. 108 runTestAsPrimaryUser( 109 NUMBER_BLOCKING_APP_TEST_CLASS_NAME, "testBlockNumberAsPrimaryUserSucceeds"); 110 setTestAppAsDefaultSmsAppForUser( 111 false /* setToSmsApp */, getDevice().getPrimaryUserId()); 112 113 // Ensure incoming call from blocked number is rejected, and unregister the phone 114 // account. 115 runTestAsPrimaryUser(CALL_BLOCKING_TEST_CLASS_NAME, "testRegisterPhoneAccount"); 116 enablePhoneAccountForUser(mPrimaryUserSerialNumber); 117 runTestAsPrimaryUser(CALL_BLOCKING_TEST_CLASS_NAME, 118 "testIncomingCallFromBlockedNumberIsRejected"); 119 runTestAsPrimaryUser(CALL_BLOCKING_TEST_CLASS_NAME, "testUnregisterPhoneAccount"); 120 121 // Run tests as secondary user. 122 assertTrue(getDevice().startUser(mSecondaryUserId)); 123 124 // Ensure that a privileged app cannot block numbers when the current user is a 125 // secondary user. 126 setTestAppAsDefaultSmsAppForUser(true /* setToSmsApp */, mSecondaryUserId); 127 runTestAsSecondaryUser(NUMBER_BLOCKING_APP_TEST_CLASS_NAME, 128 "testSecondaryUserCannotBlockNumbers"); 129 setTestAppAsDefaultSmsAppForUser(false /* setToSmsApp */, mSecondaryUserId); 130 131 // Calls should be blocked by Telecom for secondary users as well. 132 runTestAsSecondaryUser(CALL_BLOCKING_TEST_CLASS_NAME, "testRegisterPhoneAccount"); 133 enablePhoneAccountForUser(mSecondaryUserSerialNumber); 134 runTestAsSecondaryUser(CALL_BLOCKING_TEST_CLASS_NAME, 135 "testIncomingCallFromBlockedNumberIsRejected"); 136 } finally { 137 // Cleanup state by unblocking the blocked number. 138 setTestAppAsDefaultSmsAppForUser( 139 true /* setToSmsApp */, getDevice().getPrimaryUserId()); 140 runTestAsPrimaryUser( 141 NUMBER_BLOCKING_APP_TEST_CLASS_NAME, "testUnblockNumberAsPrimaryUserSucceeds"); 142 } 143 } 144 createSecondaryUser()145 private void createSecondaryUser() throws Exception { 146 mSecondaryUserId = getDevice().createUser(SECONDARY_USER_NAME); 147 getDevice().waitForDeviceAvailable(); 148 } 149 installTestAppForUser(int userId)150 private void installTestAppForUser(int userId) throws Exception { 151 LogUtil.CLog.logAndDisplay(Log.LogLevel.INFO, "Installing test app for user: " + userId); 152 File testAppFile = MigrationHelper.getTestFile(mCtsBuild, TEST_APK); 153 String installResult = getDevice().installPackageForUser( 154 testAppFile, true /*reinstall*/, userId); 155 assertNull(String.format( 156 "failed to install number blocking test app. Reason: %s", installResult), 157 installResult); 158 } 159 runTestAsPrimaryUser(String className, String methodName)160 private void runTestAsPrimaryUser(String className, String methodName) throws Exception { 161 runTestAsUser(className, methodName, getDevice().getPrimaryUserId()); 162 } 163 runTestAsSecondaryUser(String className, String methodName)164 private void runTestAsSecondaryUser(String className, String methodName) throws Exception { 165 runTestAsUser(className, methodName, mSecondaryUserId); 166 } 167 runTestAsUser(String className, String methodName, int userId)168 private void runTestAsUser(String className, String methodName, int userId) throws Exception { 169 LogUtil.CLog.logAndDisplay(Log.LogLevel.INFO, "Running %s.%s for user: %d", 170 className, methodName, userId); 171 RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner( 172 NUMBER_BLOCKING_TESTS_PKG, 173 "android.support.test.runner.AndroidJUnitRunner", 174 getDevice().getIDevice()); 175 testRunner.addInstrumentationArg("blocked_number", BLOCKED_NUMBER); 176 testRunner.addInstrumentationArg("phone_account_id", PHONE_ACCOUNT_ID); 177 testRunner.setMethodName(NUMBER_BLOCKING_TESTS_PKG + "." + className, methodName); 178 CollectingTestListener listener = new CollectingTestListener(); 179 getDevice().runInstrumentationTestsAsUser(testRunner, userId, listener); 180 assertEquals(1, listener.getNumTotalTests()); 181 assertFalse(listener.getCurrentRunResults().getTestResults().keySet().toString(), 182 listener.getCurrentRunResults().hasFailedTests()); 183 } 184 enablePhoneAccountForUser(int userSerialNumber)185 private void enablePhoneAccountForUser(int userSerialNumber) throws Exception { 186 String command = String.format( 187 "telecom set-phone-account-enabled %s\\/%s.%s\\$%s %s %d", 188 NUMBER_BLOCKING_TESTS_PKG, 189 NUMBER_BLOCKING_TESTS_PKG, 190 CALL_BLOCKING_TEST_CLASS_NAME, 191 TEST_APP_CONNECTION_SERVICE_NAME, 192 PHONE_ACCOUNT_ID, 193 userSerialNumber); 194 String commandResponse = getDevice().executeShellCommand(command); 195 assertTrue(commandResponse, commandResponse.contains("Success")); 196 } 197 setTestAppAsDefaultSmsAppForUser(boolean setToSmsApp, int userId)198 private void setTestAppAsDefaultSmsAppForUser(boolean setToSmsApp, int userId) 199 throws Exception { 200 String command = String.format("appops set --user %d %s WRITE_SMS %s", userId, 201 NUMBER_BLOCKING_TESTS_PKG, 202 setToSmsApp ? "allow" : "default"); 203 assertEquals("", getDevice().executeShellCommand(command)); 204 } 205 206 // TODO: Replace this with API in ITestDevice once it is available. getUserSerialNumber(int userId)207 private int getUserSerialNumber(int userId) throws DeviceNotAvailableException { 208 // dumpsys user return lines like "UserInfo{0:Owner:13} serialNo=0" 209 String commandOutput = getDevice().executeShellCommand("dumpsys user"); 210 String[] tokens = commandOutput.split("\\n"); 211 for (String token : tokens) { 212 token = token.trim(); 213 if (token.contains("UserInfo{" + userId + ":")) { 214 String[] split = token.split("serialNo="); 215 assertTrue(split.length == 2); 216 int serialNumber = Integer.parseInt(split[1]); 217 LogUtil.CLog.logAndDisplay( 218 Log.LogLevel.INFO, 219 String.format("Serial number of user %d : %d", userId, serialNumber)); 220 return serialNumber; 221 } 222 } 223 fail("Couldn't find user " + userId); 224 return -1; 225 } 226 } 227