1 /* 2 * Copyright (C) 2019 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.telephony.ims.cts; 18 19 import static junit.framework.TestCase.assertEquals; 20 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.fail; 23 import static org.junit.Assert.assertTrue; 24 import static org.junit.Assume.assumeTrue; 25 26 import android.annotation.NonNull; 27 import android.content.BroadcastReceiver; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.IntentFilter; 31 import android.database.ContentObserver; 32 import android.net.Uri; 33 import android.os.Handler; 34 import android.os.Looper; 35 import android.os.PersistableBundle; 36 import android.telephony.AccessNetworkConstants; 37 import android.telephony.CarrierConfigManager; 38 import android.telephony.Rlog; 39 import android.telephony.ServiceState; 40 import android.telephony.SubscriptionManager; 41 import android.telephony.TelephonyCallback; 42 import android.telephony.TelephonyManager; 43 import android.telephony.ims.ImsException; 44 import android.telephony.ims.ImsManager; 45 import android.telephony.ims.ImsMmTelManager; 46 import android.telephony.ims.ImsStateCallback; 47 import android.telephony.ims.feature.MmTelFeature; 48 49 import androidx.test.ext.junit.runners.AndroidJUnit4; 50 import androidx.test.platform.app.InstrumentationRegistry; 51 52 import com.android.compatibility.common.util.ShellIdentityUtils; 53 import com.android.internal.telephony.flags.Flags; 54 55 import org.junit.AfterClass; 56 import org.junit.Before; 57 import org.junit.BeforeClass; 58 import org.junit.Test; 59 import org.junit.runner.RunWith; 60 61 import java.util.concurrent.CountDownLatch; 62 import java.util.concurrent.LinkedBlockingQueue; 63 import java.util.concurrent.Semaphore; 64 import java.util.concurrent.TimeUnit; 65 66 @RunWith(AndroidJUnit4.class) 67 public class ImsMmTelManagerTest { 68 private static final String TAG = "ImsMmTelManagerTest"; 69 private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(5); 70 71 // Copied from CarrierConfigManager, since these keys is inappropriately marked as @hide 72 private static final String KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL = 73 "carrier_volte_override_wfc_provisioning_bool"; 74 private static final String KEY_EDITABLE_WFC_MODE_BOOL = "editable_wfc_mode_bool"; 75 private static final String KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL = 76 "use_wfc_home_network_mode_in_roaming_network_bool"; 77 private static final String KEY_EDITABLE_WFC_ROAMING_MODE_BOOL = 78 "editable_wfc_roaming_mode_bool"; 79 80 private static final String KEY_OVERRIDE_WFC_ROAMING_MODE_WHILE_USING_NTN_BOOL = 81 "override_wfc_roaming_mode_while_using_ntn_bool"; 82 83 private static final String KEY_SATELLITE_ATTACH_SUPPORTED_BOOL = 84 "satellite_attach_supported_bool"; 85 86 private static int sTestSub = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 87 private static Handler sHandler; 88 private static CarrierConfigReceiver sReceiver; 89 private static TelephonyManager sTelephonyManager; 90 91 private static class CarrierConfigReceiver extends BroadcastReceiver { 92 private CountDownLatch mLatch = new CountDownLatch(1); 93 private final int mSubId; 94 CarrierConfigReceiver(int subId)95 CarrierConfigReceiver(int subId) { 96 mSubId = subId; 97 } 98 99 @Override onReceive(Context context, Intent intent)100 public void onReceive(Context context, Intent intent) { 101 if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) { 102 int subId = intent.getIntExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, -1); 103 if (mSubId == subId) { 104 mLatch.countDown(); 105 } 106 } 107 } 108 clearQueue()109 void clearQueue() { 110 mLatch = new CountDownLatch(1); 111 } 112 waitForCarrierConfigChanged()113 void waitForCarrierConfigChanged() throws Exception { 114 mLatch.await(TIMEOUT, TimeUnit.MILLISECONDS); 115 } 116 } 117 118 private static class ServiceStateListenerTest extends TelephonyCallback 119 implements TelephonyCallback.ServiceStateListener { 120 121 private final Semaphore mNonTerrestrialNetworkSemaphore = new Semaphore(0); 122 123 @Override onServiceStateChanged(ServiceState serviceState)124 public void onServiceStateChanged(ServiceState serviceState) { 125 logd("onServiceStateChanged: serviceState=" + serviceState); 126 127 try { 128 if (serviceState.isUsingNonTerrestrialNetwork()) { 129 mNonTerrestrialNetworkSemaphore.release(); 130 } 131 } catch (Exception e) { 132 loge("onServiceStateChanged: Got exception=" + e); 133 } 134 } 135 waitForNonTerrestrialNetworkConnection()136 public boolean waitForNonTerrestrialNetworkConnection() { 137 try { 138 if (!mNonTerrestrialNetworkSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) { 139 loge("Timeout to connect to non-terrestrial network"); 140 return false; 141 } 142 } catch (Exception e) { 143 loge("ServiceStateListenerTest waitForNonTerrestrialNetworkConnection: " 144 + "Got exception=" + e); 145 return false; 146 } 147 return true; 148 } 149 clearServiceStateChanges()150 public void clearServiceStateChanges() { 151 logd("clearServiceStateChanges()"); 152 mNonTerrestrialNetworkSemaphore.drainPermits(); 153 } 154 } 155 156 @BeforeClass beforeAllTests()157 public static void beforeAllTests() { 158 // assumeTrue() in @BeforeClass is not supported by our test runner. 159 // Resort to the early exit. 160 if (!ImsUtils.shouldTestImsService()) { 161 return; 162 } 163 164 sTestSub = ImsUtils.getPreferredActiveSubId(); 165 166 if (Looper.getMainLooper() == null) { 167 Looper.prepareMainLooper(); 168 } 169 sHandler = new Handler(Looper.getMainLooper()); 170 171 sReceiver = new CarrierConfigReceiver(sTestSub); 172 IntentFilter filter = new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 173 // ACTION_CARRIER_CONFIG_CHANGED is sticky, so we will get a callback right away. 174 getContext().registerReceiver(sReceiver, filter, Context.RECEIVER_EXPORTED_UNAUDITED); 175 176 sTelephonyManager = InstrumentationRegistry.getInstrumentation().getContext() 177 .getSystemService(TelephonyManager.class); 178 } 179 180 @AfterClass afterAllTests()181 public static void afterAllTests() { 182 // assumeTrue() in @AfterClass is not supported by our test runner. 183 // Resort to the early exit. 184 if (!ImsUtils.shouldTestImsService()) { 185 return; 186 } 187 188 if (sReceiver != null) { 189 getContext().unregisterReceiver(sReceiver); 190 sReceiver = null; 191 } 192 } 193 194 @Before beforeTest()195 public void beforeTest() { 196 assumeTrue(ImsUtils.shouldTestImsService()); 197 198 if (!SubscriptionManager.isValidSubscriptionId(sTestSub)) { 199 fail("This test requires that there is a SIM in the device!"); 200 } 201 } 202 203 @Test testGetVoWiFiSetting_noPermission()204 public void testGetVoWiFiSetting_noPermission() { 205 try { 206 ImsManager imsManager = getContext().getSystemService(ImsManager.class); 207 ImsMmTelManager mMmTelManager = imsManager.getImsMmTelManager(sTestSub); 208 boolean isEnabled = mMmTelManager.isVoWiFiSettingEnabled(); 209 fail("Expected SecurityException for missing permissions"); 210 } catch (SecurityException ex) { 211 /* Expected */ 212 } 213 } 214 215 /** 216 * Given the advanced calling setting is editable and not hidden 217 * (see {@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL}, and 218 * {@link CarrierConfigManager#KEY_HIDE_ENHANCED_4G_LTE_BOOL}), set the advanced 219 * calling setting and ensure the correct calling setting is returned. Also ensure the 220 * ContentObserver is triggered properly. 221 */ 222 @Test testAdvancedCallingSetting()223 public void testAdvancedCallingSetting() throws Exception { 224 // Ensure advanced calling setting is editable. 225 PersistableBundle bundle = new PersistableBundle(); 226 bundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL, true); 227 bundle.putBoolean(CarrierConfigManager.KEY_HIDE_ENHANCED_4G_LTE_BOOL, false); 228 overrideCarrierConfig(bundle); 229 // Register Observer 230 Uri callingUri = Uri.withAppendedPath( 231 SubscriptionManager.ADVANCED_CALLING_ENABLED_CONTENT_URI, "" + sTestSub); 232 CountDownLatch contentObservedLatch = new CountDownLatch(1); 233 ContentObserver observer = createObserver(callingUri, contentObservedLatch); 234 235 ImsManager imsManager = getContext().getSystemService(ImsManager.class); 236 ImsMmTelManager mMmTelManager = imsManager.getImsMmTelManager(sTestSub); 237 boolean isEnabled = ShellIdentityUtils.invokeMethodWithShellPermissions(mMmTelManager, 238 ImsMmTelManager::isAdvancedCallingSettingEnabled); 239 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 240 (m) -> m.setAdvancedCallingSettingEnabled(!isEnabled)); 241 242 waitForLatch(contentObservedLatch, observer); 243 boolean isEnabledResult = ShellIdentityUtils.invokeMethodWithShellPermissions(mMmTelManager, 244 ImsMmTelManager::isAdvancedCallingSettingEnabled); 245 assertEquals("isAdvancedCallingSettingEnabled does not reflect the new value set by " 246 + "setAdvancedCallingSettingEnabled", !isEnabled, isEnabledResult); 247 248 // Set back to default 249 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 250 (m) -> m.setAdvancedCallingSettingEnabled(isEnabled)); 251 // restore original carrier config. 252 overrideCarrierConfig(null); 253 } 254 255 /** 256 * Set the VT setting and ensure it is queried successfully. Also ensure the ContentObserver 257 * is triggered properly. 258 */ 259 @Test testVtSetting()260 public void testVtSetting() throws Exception { 261 // Register Observer 262 Uri callingUri = Uri.withAppendedPath( 263 SubscriptionManager.VT_ENABLED_CONTENT_URI, "" + sTestSub); 264 CountDownLatch contentObservedLatch = new CountDownLatch(1); 265 ContentObserver observer = createObserver(callingUri, contentObservedLatch); 266 267 ImsManager imsManager = getContext().getSystemService(ImsManager.class); 268 ImsMmTelManager mMmTelManager = imsManager.getImsMmTelManager(sTestSub); 269 boolean isEnabled = ShellIdentityUtils.invokeMethodWithShellPermissions(mMmTelManager, 270 ImsMmTelManager::isVtSettingEnabled); 271 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 272 (m) -> m.setVtSettingEnabled(!isEnabled)); 273 274 waitForLatch(contentObservedLatch, observer); 275 boolean isEnabledResult = ShellIdentityUtils.invokeMethodWithShellPermissions(mMmTelManager, 276 ImsMmTelManager::isVtSettingEnabled); 277 assertEquals("isVtSettingEnabled does not match the value set by setVtSettingEnabled", 278 !isEnabled, isEnabledResult); 279 280 // Set back to default 281 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 282 (m) -> m.setVtSettingEnabled(isEnabled)); 283 } 284 285 /** 286 * Set the VoWiFi setting and ensure it is queried successfully. Also ensure the ContentObserver 287 * is triggered properly. 288 */ 289 @Test testVoWiFiSetting()290 public void testVoWiFiSetting() throws Exception { 291 PersistableBundle bundle = new PersistableBundle(); 292 // Do not worry about provisioning for this test 293 bundle.putBoolean(KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL, false); 294 bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL, false); 295 overrideCarrierConfig(bundle); 296 // Register Observer 297 Uri callingUri = Uri.withAppendedPath( 298 SubscriptionManager.WFC_ENABLED_CONTENT_URI, "" + sTestSub); 299 CountDownLatch contentObservedLatch = new CountDownLatch(1); 300 ContentObserver observer = createObserver(callingUri, contentObservedLatch); 301 302 ImsManager imsManager = getContext().getSystemService(ImsManager.class); 303 ImsMmTelManager mMmTelManager = imsManager.getImsMmTelManager(sTestSub); 304 305 boolean isEnabled = ShellIdentityUtils.invokeMethodWithShellPermissions(mMmTelManager, 306 ImsMmTelManager::isVoWiFiSettingEnabled); 307 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 308 (m) -> m.setVoWiFiSettingEnabled(!isEnabled)); 309 310 waitForLatch(contentObservedLatch, observer); 311 boolean isEnabledResult = ShellIdentityUtils.invokeMethodWithShellPermissions(mMmTelManager, 312 ImsMmTelManager::isVoWiFiSettingEnabled); 313 assertEquals("isVoWiFiSettingEnabled did not match value set by setVoWiFiSettingEnabled", 314 !isEnabled, isEnabledResult); 315 316 // Set back to default 317 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 318 (m) -> m.setVoWiFiSettingEnabled(isEnabled)); 319 overrideCarrierConfig(null); 320 } 321 322 /** 323 * Set the cross SIM setting and ensure it is queried successfully. 324 * Also ensure the ContentObserver is triggered properly. 325 */ 326 @Test testCrossSIMSetting()327 public void testCrossSIMSetting() throws Exception { 328 PersistableBundle bundle = new PersistableBundle(); 329 // Do not worry about provisioning for this test 330 bundle.putBoolean(KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL, false); 331 bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL, false); 332 overrideCarrierConfig(bundle); 333 // Register Observer 334 Uri callingUri = Uri.withAppendedPath( 335 SubscriptionManager.CROSS_SIM_ENABLED_CONTENT_URI, "" + sTestSub); 336 CountDownLatch contentObservedLatch = new CountDownLatch(1); 337 ContentObserver observer = createObserver(callingUri, contentObservedLatch); 338 339 ImsManager imsManager = getContext().getSystemService(ImsManager.class); 340 ImsMmTelManager mMmTelManager = imsManager.getImsMmTelManager(sTestSub); 341 342 boolean isEnabled = ShellIdentityUtils.invokeThrowableMethodWithShellPermissions( 343 mMmTelManager, ImsMmTelManager::isCrossSimCallingEnabled, ImsException.class, 344 "android.permission.READ_PRIVILEGED_PHONE_STATE"); 345 ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(mMmTelManager, 346 (m) -> m.setCrossSimCallingEnabled(!isEnabled), ImsException.class, 347 "android.permission.MODIFY_PHONE_STATE"); 348 349 waitForLatch(contentObservedLatch, observer); 350 boolean isEnabledResult = ShellIdentityUtils.invokeThrowableMethodWithShellPermissions( 351 mMmTelManager, 352 ImsMmTelManager::isCrossSimCallingEnabled, 353 ImsException.class, 354 "android.permission.READ_PRIVILEGED_PHONE_STATE"); 355 assertEquals("isCrossSimCallingEnabled did not match" 356 + "value set by setCrossSimCallingEnabled", 357 !isEnabled, isEnabledResult); 358 359 // Set back to default 360 ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(mMmTelManager, 361 (m) -> m.setCrossSimCallingEnabled(isEnabled), 362 ImsException.class, 363 "android.permission.MODIFY_PHONE_STATE"); 364 overrideCarrierConfig(null); 365 } 366 367 /** 368 * Set the VoWiFi roaming setting and ensure it is queried successfully. Also ensure the 369 * ContentObserver is triggered properly. 370 */ 371 @Test testVoWiFiRoamingSetting()372 public void testVoWiFiRoamingSetting() throws Exception { 373 Uri callingUri = Uri.withAppendedPath( 374 SubscriptionManager.WFC_ROAMING_ENABLED_CONTENT_URI, "" + sTestSub); 375 CountDownLatch contentObservedLatch = new CountDownLatch(1); 376 ContentObserver observer = createObserver(callingUri, contentObservedLatch); 377 378 ImsManager imsManager = getContext().getSystemService(ImsManager.class); 379 ImsMmTelManager mMmTelManager = imsManager.getImsMmTelManager(sTestSub); 380 boolean isEnabled = ShellIdentityUtils.invokeMethodWithShellPermissions(mMmTelManager, 381 ImsMmTelManager::isVoWiFiRoamingSettingEnabled); 382 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 383 (m) -> m.setVoWiFiRoamingSettingEnabled(!isEnabled)); 384 385 waitForLatch(contentObservedLatch, observer); 386 boolean isEnabledResult = ShellIdentityUtils.invokeMethodWithShellPermissions(mMmTelManager, 387 ImsMmTelManager::isVoWiFiRoamingSettingEnabled); 388 assertEquals("isVoWiFiRoamingSettingEnabled result does not match the value set by " 389 + "setVoWiFiRoamingSettingEnabled", !isEnabled, isEnabledResult); 390 391 // Set back to default 392 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 393 (m) -> m.setVoWiFiRoamingSettingEnabled(isEnabled)); 394 } 395 396 /** 397 * Expect to fail when Set the VoWiFi Mode setting withour proper permission 398 */ 399 @Test testGetVoWiFiModeSetting_noPermission()400 public void testGetVoWiFiModeSetting_noPermission() throws Exception { 401 try { 402 ImsManager imsManager = getContext().getSystemService(ImsManager.class); 403 ImsMmTelManager mMmTelManager = imsManager.getImsMmTelManager(sTestSub); 404 int oldMode = mMmTelManager.getVoWiFiModeSetting(); 405 fail("Expected SecurityException for missing permissoins"); 406 } catch (SecurityException ex) { 407 /* Expected */ 408 } 409 410 } 411 412 /** 413 * Expect to fail when Set the VoWiFi Mode setting withour proper permission 414 */ 415 @Test testGetVoWiFiRoamingModeSetting_noPermission()416 public void testGetVoWiFiRoamingModeSetting_noPermission() throws Exception { 417 try { 418 ImsManager imsManager = getContext().getSystemService(ImsManager.class); 419 ImsMmTelManager mMmTelManager = imsManager.getImsMmTelManager(sTestSub); 420 int oldMode = mMmTelManager.getVoWiFiRoamingModeSetting(); 421 fail("Expected SecurityException for missing permissoins"); 422 } catch (SecurityException ex) { 423 /* Expected */ 424 } 425 426 } 427 428 429 /** 430 * Set the VoWiFi Mode setting and ensure the ContentResolver is triggered as well. 431 */ 432 @Test testVoWiFiModeSetting()433 public void testVoWiFiModeSetting() throws Exception { 434 PersistableBundle bundle = new PersistableBundle(); 435 bundle.putBoolean(KEY_EDITABLE_WFC_MODE_BOOL, true); 436 overrideCarrierConfig(bundle); 437 // Register Observer 438 Uri callingUri = Uri.withAppendedPath( 439 SubscriptionManager.WFC_MODE_CONTENT_URI, "" + sTestSub); 440 CountDownLatch contentObservedLatch = new CountDownLatch(1); 441 ContentObserver observer = createObserver(callingUri, contentObservedLatch); 442 443 ImsManager imsManager = getContext().getSystemService(ImsManager.class); 444 ImsMmTelManager mMmTelManager = imsManager.getImsMmTelManager(sTestSub); 445 int oldMode = ShellIdentityUtils.invokeMethodWithShellPermissions(mMmTelManager, 446 ImsMmTelManager::getVoWiFiModeSetting); 447 // Keep the mode in the bounds 0-2 448 int newMode = (oldMode + 1) % 3; 449 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 450 (m) -> m.setVoWiFiModeSetting(newMode)); 451 452 waitForLatch(contentObservedLatch, observer); 453 int newModeResult = ShellIdentityUtils.invokeMethodWithShellPermissions(mMmTelManager, 454 ImsMmTelManager::getVoWiFiModeSetting); 455 assertEquals(newMode, newModeResult); 456 457 // Set back to default 458 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 459 (m) -> m.setVoWiFiModeSetting(oldMode)); 460 overrideCarrierConfig(null); 461 } 462 463 /** 464 * Set the VoWiFi Mode setting and ensure the ContentResolver is triggered as well. 465 */ 466 @Test testVoWiFiRoamingModeSetting()467 public void testVoWiFiRoamingModeSetting() throws Exception { 468 PersistableBundle bundle = new PersistableBundle(); 469 // Ensure the WFC roaming mode will be changed properly 470 bundle.putBoolean(KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL, false); 471 bundle.putBoolean(KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, true); 472 overrideCarrierConfig(bundle); 473 // Register Observer 474 Uri callingUri = Uri.withAppendedPath( 475 SubscriptionManager.WFC_ROAMING_MODE_CONTENT_URI, "" + sTestSub); 476 CountDownLatch contentObservedLatch = new CountDownLatch(1); 477 ContentObserver observer = createObserver(callingUri, contentObservedLatch); 478 479 ImsManager imsManager = getContext().getSystemService(ImsManager.class); 480 ImsMmTelManager mMmTelManager = imsManager.getImsMmTelManager(sTestSub); 481 int oldMode = ShellIdentityUtils.invokeMethodWithShellPermissions(mMmTelManager, 482 ImsMmTelManager::getVoWiFiRoamingModeSetting); 483 // Keep the mode in the bounds 0-2 484 int newMode = (oldMode + 1) % 3; 485 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 486 (m) -> m.setVoWiFiRoamingModeSetting(newMode)); 487 488 waitForLatch(contentObservedLatch, observer); 489 int newModeResult = ShellIdentityUtils.invokeMethodWithShellPermissions(mMmTelManager, 490 ImsMmTelManager::getVoWiFiRoamingModeSetting); 491 assertEquals("getVoWiFiRoamingModeSetting was not set to value set by" 492 + "setVoWiFiRoamingModeSetting", newMode, newModeResult); 493 494 // Set back to default 495 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 496 (m) -> m.setVoWiFiRoamingModeSetting(oldMode)); 497 overrideCarrierConfig(null); 498 } 499 500 @Test testVoWiFiRoamingModeSettingUsingNonTerrestrialNetwork()501 public void testVoWiFiRoamingModeSettingUsingNonTerrestrialNetwork() throws Exception { 502 if (!Flags.carrierEnabledSatelliteFlag()) { 503 return; 504 } 505 506 // Get original VoWiFi roaming mode 507 ImsManager imsManager = getContext().getSystemService(ImsManager.class); 508 ImsMmTelManager mMmTelManager = imsManager.getImsMmTelManager(sTestSub); 509 int oldMode = ShellIdentityUtils.invokeMethodWithShellPermissions(mMmTelManager, 510 ImsMmTelManager::getVoWiFiRoamingModeSetting); 511 512 // Register service state listener 513 ServiceStateListenerTest serviceStateListener = new ServiceStateListenerTest(); 514 serviceStateListener.clearServiceStateChanges(); 515 sTelephonyManager.registerTelephonyCallback(getContext().getMainExecutor(), 516 serviceStateListener); 517 518 // Override carrier config 519 PersistableBundle bundle = new PersistableBundle(); 520 bundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true); 521 bundle.putBoolean(KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL, false); 522 bundle.putBoolean(KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, true); 523 bundle.putBoolean(KEY_OVERRIDE_WFC_ROAMING_MODE_WHILE_USING_NTN_BOOL, true); 524 String plmn = sTelephonyManager.getNetworkOperator(sTestSub); 525 PersistableBundle plmnBundle = new PersistableBundle(); 526 int[] intArray1 = {3, 5}; 527 plmnBundle.putIntArray(plmn, intArray1); 528 bundle.putPersistableBundle( 529 CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE, 530 plmnBundle); 531 532 try { 533 overrideCarrierConfig(bundle); 534 assertTrue(serviceStateListener.waitForNonTerrestrialNetworkConnection()); 535 536 // Register Observer 537 Uri callingUri = Uri.withAppendedPath( 538 SubscriptionManager.WFC_ROAMING_MODE_CONTENT_URI, "" + sTestSub); 539 CountDownLatch contentObservedLatch = new CountDownLatch(1); 540 ContentObserver observer = createObserver(callingUri, contentObservedLatch); 541 542 // Set VoWiFi roaming mode to CELLULAR_PREFERRED 543 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 544 (m) -> m.setVoWiFiRoamingModeSetting( 545 ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED)); 546 waitForLatch(contentObservedLatch, observer); 547 548 int newModeResult = ShellIdentityUtils.invokeMethodWithShellPermissions(mMmTelManager, 549 ImsMmTelManager::getVoWiFiRoamingModeSetting); 550 assertEquals(ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED, newModeResult); 551 } finally { 552 // Set back to default 553 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 554 (m) -> m.setVoWiFiRoamingModeSetting(oldMode)); 555 overrideCarrierConfig(null); 556 } 557 } 558 559 /** 560 * Test Permissions on various APIs. 561 */ 562 @Test testMethodPermissions()563 public void testMethodPermissions() throws Exception { 564 ImsManager imsManager = getContext().getSystemService(ImsManager.class); 565 ImsMmTelManager mMmTelManager = imsManager.getImsMmTelManager(sTestSub); 566 // setRttCapabilitySetting 567 try { 568 mMmTelManager.setRttCapabilitySetting(false); 569 fail("setRttCapabilitySetting requires MODIFY_PHONE_STATE permission."); 570 } catch (SecurityException e) { 571 //expected 572 } 573 try { 574 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 575 (m) -> m.setRttCapabilitySetting(false), 576 "android.permission.MODIFY_PHONE_STATE"); 577 } catch (SecurityException e) { 578 fail("setRttCapabilitySetting requires MODIFY_PHONE_STATE permission."); 579 } 580 // setVoWiFiNonPersistent 581 try { 582 mMmTelManager.setVoWiFiNonPersistent(true, 583 ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED); 584 fail("setVoWiFiNonPersistent requires MODIFY_PHONE_STATE permission."); 585 } catch (SecurityException e) { 586 //expected 587 } 588 try { 589 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager, 590 (m) -> m.setVoWiFiNonPersistent(true, 591 ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED), 592 "android.permission.MODIFY_PHONE_STATE"); 593 } catch (SecurityException e) { 594 fail("setVoWiFiNonPersistent requires MODIFY_PHONE_STATE permission."); 595 } 596 597 try { 598 mMmTelManager.isVtSettingEnabled(); 599 fail("isVtSettingEnabled requires READ_PRECISE_PHONE_STATE permission."); 600 } catch (SecurityException e) { 601 //expected 602 } 603 604 try { 605 mMmTelManager.isAdvancedCallingSettingEnabled(); 606 fail("isAdvancedCallingSettingEnabled requires READ_PRECISE_PHONE_STATE."); 607 } catch (SecurityException e) { 608 //expected 609 } 610 611 try { 612 mMmTelManager.isVoWiFiRoamingSettingEnabled(); 613 fail("isVoWiFiRoamingSettingEnabled requires READ_PRECISE_PHONE_STATE permission."); 614 } catch (SecurityException e) { 615 //expected 616 } 617 618 try { 619 mMmTelManager.isVoWiFiSettingEnabled(); 620 fail("isVoWiFiSettingEnabled requires READ_PRECISE_PHONE_STATE permission."); 621 } catch (SecurityException e) { 622 //expected 623 } 624 625 try { 626 mMmTelManager.isTtyOverVolteEnabled(); 627 fail("isTtyOverVolteEnabled requires READ_PRIVILEGED_PHONE_STATE permission."); 628 } catch (SecurityException e) { 629 //expected 630 } 631 try { 632 mMmTelManager.isSupported(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, 633 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, Runnable::run, (result) -> { }); 634 fail("isSupported requires READ_PRIVILEGED_PHONE_STATE permission."); 635 } catch (SecurityException e) { 636 //expected 637 } 638 try { 639 mMmTelManager.getRegistrationState(Runnable::run, (result) -> { }); 640 fail("getRegistrationState requires READ_PRECISE_PHONE_STATE permission."); 641 } catch (SecurityException e) { 642 //expected 643 } 644 try { 645 mMmTelManager.getRegistrationTransportType(Runnable::run, (result) -> { }); 646 fail("getRegistrationTransportType requires READ_PRIVILEGED_PHONE_STATE permission."); 647 } catch (SecurityException e) { 648 //expected 649 } 650 651 try { 652 mMmTelManager.isSupported(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, 653 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, Runnable::run, (result) -> { }); 654 fail("isSupported requires READ_PRIVILEGED_PHONE_STATE permission."); 655 } catch (SecurityException e) { 656 //expected 657 } 658 659 try { 660 ShellIdentityUtils.invokeMethodWithShellPermissions(mMmTelManager, 661 ImsMmTelManager::isTtyOverVolteEnabled, 662 "android.permission.READ_PRIVILEGED_PHONE_STATE"); 663 } catch (SecurityException e) { 664 fail("isTtyOverVolteEnabled requires READ_PRIVILEGED_PHONE_STATE permission."); 665 } 666 try { 667 LinkedBlockingQueue<Boolean> resultQueue = new LinkedBlockingQueue<>(1); 668 ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(mMmTelManager, 669 (m) -> m.isSupported(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, 670 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, 671 // Run on the binder thread. 672 Runnable::run, 673 resultQueue::offer), ImsException.class, 674 "android.permission.READ_PRIVILEGED_PHONE_STATE"); 675 assertNotNull(resultQueue.poll(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)); 676 } catch (SecurityException e) { 677 fail("isSupported requires READ_PRIVILEGED_PHONE_STATE permission."); 678 } catch (ImsException ignore) { 679 // We are only testing method permissions here, so the actual ImsException does not 680 // matter, since it shows that the permission check passed. 681 } 682 try { 683 LinkedBlockingQueue<Integer> resultQueue = new LinkedBlockingQueue<>(1); 684 ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(mMmTelManager, 685 (m) -> m.getRegistrationState(Runnable::run, resultQueue::offer), 686 ImsException.class, "android.permission.READ_PRIVILEGED_PHONE_STATE"); 687 assertNotNull(resultQueue.poll(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)); 688 } catch (SecurityException e) { 689 fail("getRegistrationState requires READ_PRIVILEGED_PHONE_STATE permission."); 690 } 691 try { 692 LinkedBlockingQueue<Integer> resultQueue = new LinkedBlockingQueue<>(1); 693 ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(mMmTelManager, 694 (m) -> m.getRegistrationTransportType(Runnable::run, resultQueue::offer), 695 ImsException.class, "android.permission.READ_PRIVILEGED_PHONE_STATE"); 696 assertNotNull(resultQueue.poll(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)); 697 } catch (SecurityException e) { 698 fail("getRegistrationTransportType requires READ_PRIVILEGED_PHONE_STATE permission."); 699 } 700 701 ImsStateCallback callback = new ImsStateCallback() { 702 @Override 703 public void onUnavailable(int reason) { } 704 @Override 705 public void onAvailable() { } 706 @Override 707 public void onError() { } 708 }; 709 710 try { 711 mMmTelManager.registerImsStateCallback(Runnable::run, callback); 712 fail("registerImsStateCallback requires READ_PRECISE_PHONE_STATE or " 713 + "READ_PRIVILEGED_PHONE_STATE permission."); 714 } catch (SecurityException e) { 715 //expected 716 } catch (ImsException ie) { 717 fail("registerImsStateCallback requires READ_PRECISE_PHONE_STATE or " 718 + "READ_PRIVILEGED_PHONE_STATE permission."); 719 } 720 721 try { 722 ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(mMmTelManager, 723 m -> m.registerImsStateCallback(Runnable::run, callback), 724 ImsException.class, "android.permission.READ_PRECISE_PHONE_STATE"); 725 } catch (SecurityException e) { 726 fail("registerImsStateCallback requires READ_PRECISE_PHONE_STATE permission."); 727 } catch (ImsException ignore) { 728 // don't care, permission check passed 729 } 730 731 try { 732 mMmTelManager.unregisterImsStateCallback(callback); 733 } catch (SecurityException e) { 734 fail("uregisterImsStateCallback requires no permission."); 735 } 736 737 try { 738 ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(mMmTelManager, 739 m -> m.registerImsStateCallback(Runnable::run, callback), 740 ImsException.class, "android.permission.READ_PRIVILEGED_PHONE_STATE"); 741 } catch (SecurityException e) { 742 fail("registerImsStateCallback requires READ_PRIVILEGED_PHONE_STATE permission."); 743 } catch (ImsException ignore) { 744 // don't care, permission check passed 745 } 746 747 try { 748 mMmTelManager.unregisterImsStateCallback(callback); 749 } catch (SecurityException e) { 750 // unreachable, already passed permission check 751 fail("uregisterImsStateCallback requires no permission."); 752 } 753 } 754 overrideCarrierConfig(PersistableBundle bundle)755 private void overrideCarrierConfig(PersistableBundle bundle) throws Exception { 756 CarrierConfigManager carrierConfigManager = getContext().getSystemService( 757 CarrierConfigManager.class); 758 sReceiver.clearQueue(); 759 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(carrierConfigManager, 760 (m) -> m.overrideConfig(sTestSub, bundle)); 761 sReceiver.waitForCarrierConfigChanged(); 762 } 763 createObserver(Uri observerUri, CountDownLatch latch)764 private ContentObserver createObserver(Uri observerUri, CountDownLatch latch) { 765 ContentObserver observer = new ContentObserver(sHandler) { 766 @Override 767 public void onChange(boolean selfChange, Uri uri) { 768 if (observerUri.equals(uri)) { 769 latch.countDown(); 770 } 771 } 772 }; 773 getContext().getContentResolver().registerContentObserver(observerUri, true, observer); 774 return observer; 775 } 776 waitForLatch(CountDownLatch latch, ContentObserver observer)777 private void waitForLatch(CountDownLatch latch, ContentObserver observer) { 778 try { 779 // Wait for the ContentObserver to fire signalling the change. 780 latch.await(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS); 781 } catch (InterruptedException e) { 782 fail("Interrupted Exception waiting for latch countdown:" + e.getMessage()); 783 } finally { 784 getContext().getContentResolver().unregisterContentObserver(observer); 785 } 786 } 787 getContext()788 private static Context getContext() { 789 return InstrumentationRegistry.getInstrumentation().getContext(); 790 } 791 logd(@onNull String log)792 protected static void logd(@NonNull String log) { 793 Rlog.d(TAG, log); 794 } 795 loge(@onNull String log)796 protected static void loge(@NonNull String log) { 797 Rlog.e(TAG, log); 798 } 799 } 800