1 /* 2 * Copyright (C) 2023 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.satellite.cts; 18 19 import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN; 20 21 import static org.junit.Assert.assertArrayEquals; 22 import static org.junit.Assert.assertEquals; 23 import static org.junit.Assert.assertFalse; 24 import static org.junit.Assert.assertNotNull; 25 import static org.junit.Assert.assertNull; 26 import static org.junit.Assert.assertTrue; 27 import static org.junit.Assert.fail; 28 29 import android.Manifest; 30 import android.annotation.NonNull; 31 import android.annotation.Nullable; 32 import android.bluetooth.BluetoothAdapter; 33 import android.content.BroadcastReceiver; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.content.pm.PackageManager; 37 import android.database.ContentObserver; 38 import android.net.wifi.WifiManager; 39 import android.nfc.NfcAdapter; 40 import android.os.Handler; 41 import android.os.Looper; 42 import android.os.OutcomeReceiver; 43 import android.os.PersistableBundle; 44 import android.provider.Settings; 45 import android.telephony.CarrierConfigManager; 46 import android.telephony.Rlog; 47 import android.telephony.SubscriptionInfo; 48 import android.telephony.SubscriptionManager; 49 import android.telephony.TelephonyManager; 50 import android.telephony.cts.SatelliteReceiver; 51 import android.telephony.cts.TelephonyManagerTest.ServiceStateRadioStateListener; 52 import android.telephony.satellite.EarfcnRange; 53 import android.telephony.satellite.EnableRequestAttributes; 54 import android.telephony.satellite.NtnSignalStrength; 55 import android.telephony.satellite.NtnSignalStrengthCallback; 56 import android.telephony.satellite.PointingInfo; 57 import android.telephony.satellite.SatelliteAccessConfiguration; 58 import android.telephony.satellite.SatelliteCapabilities; 59 import android.telephony.satellite.SatelliteCapabilitiesCallback; 60 import android.telephony.satellite.SatelliteCommunicationAccessStateCallback; 61 import android.telephony.satellite.SatelliteDatagram; 62 import android.telephony.satellite.SatelliteDatagramCallback; 63 import android.telephony.satellite.SatelliteDisallowedReasonsCallback; 64 import android.telephony.satellite.SatelliteInfo; 65 import android.telephony.satellite.SatelliteManager; 66 import android.telephony.satellite.SatelliteModemStateCallback; 67 import android.telephony.satellite.SatellitePosition; 68 import android.telephony.satellite.SatelliteProvisionStateCallback; 69 import android.telephony.satellite.SatelliteSubscriberInfo; 70 import android.telephony.satellite.SatelliteSubscriberProvisionStatus; 71 import android.telephony.satellite.SatelliteTransmissionUpdateCallback; 72 import android.telephony.satellite.SelectedNbIotSatelliteSubscriptionCallback; 73 import android.telephony.satellite.SystemSelectionSpecifier; 74 import android.text.TextUtils; 75 import android.util.Log; 76 import android.util.Pair; 77 import android.uwb.UwbManager; 78 79 import androidx.test.InstrumentationRegistry; 80 81 import com.android.compatibility.common.util.ShellIdentityUtils; 82 83 import java.util.ArrayList; 84 import java.util.Arrays; 85 import java.util.List; 86 import java.util.UUID; 87 import java.util.concurrent.CountDownLatch; 88 import java.util.concurrent.LinkedBlockingQueue; 89 import java.util.concurrent.Semaphore; 90 import java.util.concurrent.TimeUnit; 91 import java.util.concurrent.atomic.AtomicReference; 92 import java.util.function.Consumer; 93 import java.util.stream.Collectors; 94 import java.util.stream.IntStream; 95 96 public class SatelliteManagerTestBase { 97 protected static String TAG = "SatelliteManagerTestBase"; 98 99 protected static final String TOKEN = "TEST_TOKEN"; 100 protected static final long TIMEOUT = TimeUnit.SECONDS.toMillis(5); 101 public static final int RADIO_HAL_VERSION_2_3 = makeRadioVersion(2, 3); 102 103 /** 104 * Since SST sets waiting time up to 10 seconds for the power off radio, the timer waiting for 105 * radio power state change should be greater than 10 seconds. 106 */ 107 protected static final long EXTERNAL_DEPENDENT_TIMEOUT = TimeUnit.SECONDS.toMillis(15); 108 109 protected static SatelliteManager sSatelliteManager; 110 protected static TelephonyManager sTelephonyManager = null; 111 112 protected UwbManager mUwbManager = null; 113 protected NfcAdapter mNfcAdapter = null; 114 protected BluetoothAdapter mBluetoothAdapter = null; 115 protected WifiManager mWifiManager = null; 116 beforeAllTestsBase()117 protected static void beforeAllTestsBase() { 118 sSatelliteManager = getContext().getSystemService(SatelliteManager.class); 119 sTelephonyManager = getContext().getSystemService(TelephonyManager.class); 120 turnRadioOn(); 121 } 122 afterAllTestsBase()123 protected static void afterAllTestsBase() { 124 sSatelliteManager = null; 125 sTelephonyManager = null; 126 } 127 shouldTestSatellite()128 protected static boolean shouldTestSatellite() { 129 if (!getContext().getPackageManager().hasSystemFeature( 130 PackageManager.FEATURE_TELEPHONY_SATELLITE)) { 131 logd("Skipping tests because FEATURE_TELEPHONY_SATELLITE is not available"); 132 return false; 133 } 134 try { 135 getContext().getSystemService(TelephonyManager.class) 136 .getHalVersion(TelephonyManager.HAL_SERVICE_RADIO); 137 } catch (IllegalStateException e) { 138 logd("Skipping tests because Telephony service is null, exception=" + e); 139 return false; 140 } 141 return true; 142 } 143 shouldTestSatelliteWithMockService()144 protected static boolean shouldTestSatelliteWithMockService() { 145 if (!getContext().getPackageManager().hasSystemFeature( 146 PackageManager.FEATURE_TELEPHONY)) { 147 logd("Skipping tests because FEATURE_TELEPHONY is not available"); 148 return false; 149 } 150 if (!getContext().getPackageManager().hasSystemFeature( 151 PackageManager.FEATURE_TELEPHONY_SATELLITE)) { 152 // Satellite test against mock service should pass on satellite-less devices, but it's 153 // still too flaky. 154 logd("Skipping tests because FEATURE_TELEPHONY_SATELLITE is not available"); 155 return false; 156 } 157 try { 158 getContext().getSystemService(TelephonyManager.class) 159 .getHalVersion(TelephonyManager.HAL_SERVICE_RADIO); 160 } catch (IllegalStateException e) { 161 logd("Skipping tests because Telephony service is null, exception=" + e); 162 return false; 163 } 164 return true; 165 } 166 getContext()167 protected static Context getContext() { 168 return InstrumentationRegistry.getContext(); 169 } 170 grantSatellitePermission()171 protected static void grantSatellitePermission() { 172 InstrumentationRegistry.getInstrumentation().getUiAutomation() 173 .adoptShellPermissionIdentity(Manifest.permission.SATELLITE_COMMUNICATION); 174 } 175 revokeSatellitePermission()176 protected static void revokeSatellitePermission() { 177 InstrumentationRegistry.getInstrumentation().getUiAutomation() 178 .dropShellPermissionIdentity(); 179 } 180 grantSatelliteAndReadBasicPhoneStatePermissions()181 protected static void grantSatelliteAndReadBasicPhoneStatePermissions() { 182 InstrumentationRegistry.getInstrumentation().getUiAutomation() 183 .adoptShellPermissionIdentity(Manifest.permission.SATELLITE_COMMUNICATION, 184 Manifest.permission.READ_BASIC_PHONE_STATE); 185 } 186 187 protected static class SatelliteTransmissionUpdateCallbackTest implements 188 SatelliteTransmissionUpdateCallback { 189 190 protected static final class DatagramStateChangeArgument { 191 protected int state; 192 protected int pendingCount; 193 protected int errorCode; 194 // Sending datagram type, should not be used as a comparison for the equals(). 195 // Because receiving case there is no datagram type. 196 protected int datagramType; 197 DatagramStateChangeArgument(int state, int pendingCount, int errorCode)198 DatagramStateChangeArgument(int state, int pendingCount, int errorCode) { 199 this.state = state; 200 this.pendingCount = pendingCount; 201 this.errorCode = errorCode; 202 this.datagramType = DATAGRAM_TYPE_UNKNOWN; 203 } 204 DatagramStateChangeArgument(int datagramType, int state, int pendingCount, int errorCode)205 DatagramStateChangeArgument(int datagramType, int state, int pendingCount, int errorCode) { 206 this.datagramType = datagramType; 207 this.state = state; 208 this.pendingCount = pendingCount; 209 this.errorCode = errorCode; 210 } 211 212 @Override equals(Object other)213 public boolean equals(Object other) { 214 if (this == other) return true; 215 if (other == null || getClass() != other.getClass()) return false; 216 DatagramStateChangeArgument that = (DatagramStateChangeArgument) other; 217 return state == that.state 218 && pendingCount == that.pendingCount 219 && errorCode == that.errorCode; 220 } 221 222 @Override toString()223 public String toString() { 224 return ("state: " + state + " pendingCount: " + pendingCount 225 + " errorCode: " + errorCode); 226 } 227 } 228 229 public PointingInfo mPointingInfo; 230 private final Semaphore mPositionChangeSemaphore = new Semaphore(0); 231 private List<DatagramStateChangeArgument> mSendDatagramStateChanges = new ArrayList<>(); 232 private final Object mSendDatagramStateChangesLock = new Object(); 233 private final Semaphore mSendSemaphore = new Semaphore(0); 234 private List<DatagramStateChangeArgument> mReceiveDatagramStateChanges = new ArrayList<>(); 235 private final Object mReceiveDatagramStateChangesLock = new Object(); 236 private final Semaphore mReceiveSemaphore = new Semaphore(0); 237 private final Object mSendDatagramRequestedLock = new Object(); 238 private final Semaphore mSendDatagramRequestedSemaphore = new Semaphore(0); 239 @SatelliteManager.DatagramType 240 private List<Integer> mSendDatagramRequestedList = new ArrayList<>(); 241 242 @Override onSatellitePositionChanged(PointingInfo pointingInfo)243 public void onSatellitePositionChanged(PointingInfo pointingInfo) { 244 logd("onSatellitePositionChanged: pointingInfo=" + pointingInfo); 245 mPointingInfo = pointingInfo; 246 247 try { 248 mPositionChangeSemaphore.release(); 249 } catch (Exception e) { 250 loge("onSatellitePositionChanged: Got exception, ex=" + e); 251 } 252 } 253 254 @Override onSendDatagramStateChanged(int state, int sendPendingCount, int errorCode)255 public void onSendDatagramStateChanged(int state, int sendPendingCount, int errorCode) { 256 logd("onSendDatagramStateChanged: state=" + state + ", sendPendingCount=" 257 + sendPendingCount + ", errorCode=" + errorCode); 258 // Implementation moved to onSendDatagramStateChanged(int, int, int, int) 259 // This callback is called only for backward compatibility after calling 260 // onSendDatagramStateChanged(int, int, int, int). This call flows is guaranteed by 261 // SatelliteManager#startTransmissionUpdates(). 262 } 263 264 @Override onSendDatagramStateChanged( int datagramType, int state, int sendPendingCount, int errorCode)265 public void onSendDatagramStateChanged( 266 int datagramType, int state, int sendPendingCount, int errorCode) { 267 logd("onSendDatagramStateChanged:datagramType=" + datagramType + ", state=" + state 268 + ", sendPendingCount=" + sendPendingCount + ", errorCode=" + errorCode); 269 synchronized (mSendDatagramStateChangesLock) { 270 mSendDatagramStateChanges.add(new DatagramStateChangeArgument(datagramType, 271 state, sendPendingCount, errorCode)); 272 } 273 274 try { 275 mSendSemaphore.release(); 276 } catch (Exception e) { 277 loge("onSendDatagramStateChanged: Got exception, ex=" + e); 278 } 279 } 280 281 @Override onReceiveDatagramStateChanged( int state, int receivePendingCount, int errorCode)282 public void onReceiveDatagramStateChanged( 283 int state, int receivePendingCount, int errorCode) { 284 logd("onReceiveDatagramStateChanged: state=" + state + ", " 285 + "receivePendingCount=" + receivePendingCount + ", errorCode=" + errorCode); 286 synchronized (mReceiveDatagramStateChangesLock) { 287 mReceiveDatagramStateChanges.add(new DatagramStateChangeArgument(state, 288 receivePendingCount, errorCode)); 289 } 290 291 try { 292 mReceiveSemaphore.release(); 293 } catch (Exception e) { 294 loge("onReceiveDatagramStateChanged: Got exception, ex=" + e); 295 } 296 } 297 298 @Override onSendDatagramRequested(int datagramType)299 public void onSendDatagramRequested(int datagramType) { 300 logd("onSendDatagramRequested: datagramType=" + datagramType); 301 synchronized (mSendDatagramRequestedLock) { 302 mSendDatagramRequestedList.add(datagramType); 303 } 304 305 try { 306 mSendDatagramRequestedSemaphore.release(); 307 } catch (Exception e) { 308 loge("onSendDatagramRequested: Got exception, ex=" + e); 309 } 310 } 311 waitUntilOnSatellitePositionChanged(int expectedNumberOfEvents)312 public boolean waitUntilOnSatellitePositionChanged(int expectedNumberOfEvents) { 313 for (int i = 0; i < expectedNumberOfEvents; i++) { 314 try { 315 if (!mPositionChangeSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) { 316 loge("Timeout to receive onSatellitePositionChanged() callback"); 317 return false; 318 } 319 } catch (Exception ex) { 320 loge("SatelliteTransmissionUpdateCallback " 321 + "waitUntilOnSatellitePositionChanged: Got exception=" + ex); 322 return false; 323 } 324 } 325 return true; 326 } 327 waitUntilOnSendDatagramStateChanged(int expectedNumberOfEvents)328 public boolean waitUntilOnSendDatagramStateChanged(int expectedNumberOfEvents) { 329 logd( 330 "waitUntilOnSendDatagramStateChanged expectedNumberOfEvents:" 331 + expectedNumberOfEvents); 332 for (int i = 0; i < expectedNumberOfEvents; i++) { 333 try { 334 if (!mSendSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) { 335 loge("Timeout to receive onSendDatagramStateChanged() callback"); 336 return false; 337 } 338 } catch (Exception ex) { 339 loge("SatelliteTransmissionUpdateCallback " 340 + "waitUntilOnSendDatagramStateChanged: Got exception=" + ex); 341 return false; 342 } 343 } 344 return true; 345 } 346 waitUntilOnReceiveDatagramStateChanged(int expectedNumberOfEvents)347 public boolean waitUntilOnReceiveDatagramStateChanged(int expectedNumberOfEvents) { 348 for (int i = 0; i < expectedNumberOfEvents; i++) { 349 try { 350 if (!mReceiveSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) { 351 loge("Timeout to receive onReceiveDatagramStateChanged()"); 352 return false; 353 } 354 } catch (Exception ex) { 355 loge("SatelliteTransmissionUpdateCallback " 356 + "waitUntilOnReceiveDatagramStateChanged: Got exception=" + ex); 357 return false; 358 } 359 } 360 return true; 361 } 362 waitUntilOnSendDatagramRequested(int expectedNumberOfEvents)363 public boolean waitUntilOnSendDatagramRequested(int expectedNumberOfEvents) { 364 logd("waitUntilOnSendDatagramRequested expectedNumberOfEvents:" 365 + expectedNumberOfEvents); 366 for (int i = 0; i < expectedNumberOfEvents; i++) { 367 try { 368 if (!mSendDatagramRequestedSemaphore.tryAcquire( 369 TIMEOUT, TimeUnit.MILLISECONDS)) { 370 loge("Timeout to receive onSendDatagramRequested() callback"); 371 return false; 372 } 373 } catch (Exception ex) { 374 loge("SatelliteTransmissionUpdateCallback " 375 + "waitUntilOnSendDatagramRequested: Got exception=" + ex); 376 return false; 377 } 378 } 379 return true; 380 } 381 clearPointingInfo()382 public void clearPointingInfo() { 383 mPointingInfo = null; 384 mPositionChangeSemaphore.drainPermits(); 385 } 386 clearSendDatagramStateChanges()387 public void clearSendDatagramStateChanges() { 388 synchronized (mSendDatagramStateChangesLock) { 389 logd("clearSendDatagramStateChanges"); 390 mSendDatagramStateChanges.clear(); 391 mSendSemaphore.drainPermits(); 392 } 393 } 394 clearReceiveDatagramStateChanges()395 public void clearReceiveDatagramStateChanges() { 396 synchronized (mReceiveDatagramStateChangesLock) { 397 logd("clearReceiveDatagramStateChanges"); 398 mReceiveDatagramStateChanges.clear(); 399 mReceiveSemaphore.drainPermits(); 400 } 401 } 402 clearSendDatagramRequested()403 public void clearSendDatagramRequested() { 404 synchronized (mSendDatagramRequestedLock) { 405 logd("clearSendDatagramRequested"); 406 mSendDatagramRequestedList.clear(); 407 mSendDatagramRequestedSemaphore.drainPermits(); 408 } 409 } 410 411 @Nullable getSendDatagramStateChange(int index)412 public DatagramStateChangeArgument getSendDatagramStateChange(int index) { 413 synchronized (mSendDatagramStateChangesLock) { 414 if (index < mSendDatagramStateChanges.size()) { 415 return mSendDatagramStateChanges.get(index); 416 } else { 417 Log.e(TAG, "getSendDatagramStateChange: invalid index= " + index 418 + " mSendDatagramStateChanges.size= " 419 + mSendDatagramStateChanges.size()); 420 return null; 421 } 422 } 423 } 424 425 @Nullable getReceiveDatagramStateChange(int index)426 public DatagramStateChangeArgument getReceiveDatagramStateChange(int index) { 427 synchronized (mReceiveDatagramStateChangesLock) { 428 if (index < mReceiveDatagramStateChanges.size()) { 429 return mReceiveDatagramStateChanges.get(index); 430 } else { 431 Log.e(TAG, "getReceiveDatagramStateChange: invalid index= " + index 432 + " mReceiveDatagramStateChanges.size= " 433 + mReceiveDatagramStateChanges.size()); 434 return null; 435 } 436 } 437 } 438 getNumOfSendDatagramStateChanges()439 public int getNumOfSendDatagramStateChanges() { 440 synchronized (mSendDatagramStateChangesLock) { 441 logd("getNumOfSendDatagramStateChanges size:" + mSendDatagramStateChanges.size()); 442 return mSendDatagramStateChanges.size(); 443 } 444 } 445 getNumOfReceiveDatagramStateChanges()446 public int getNumOfReceiveDatagramStateChanges() { 447 synchronized (mReceiveDatagramStateChangesLock) { 448 return mReceiveDatagramStateChanges.size(); 449 } 450 } 451 452 @SatelliteManager.DatagramType getSendDatagramRequestedType(int index)453 public int getSendDatagramRequestedType(int index) { 454 synchronized (mSendDatagramRequestedLock) { 455 if (index < mSendDatagramRequestedList.size()) { 456 return mSendDatagramRequestedList.get(index); 457 } else { 458 Log.e(TAG, "getSendDatagramRequestedType: invalid index= " + index 459 + " mSendDatagramRequestedList.size= " 460 + mSendDatagramRequestedList.size()); 461 return DATAGRAM_TYPE_UNKNOWN; 462 } 463 } 464 } 465 getNumOfSendDatagramRequestedChanges()466 public int getNumOfSendDatagramRequestedChanges() { 467 synchronized (mSendDatagramRequestedLock) { 468 return mSendDatagramRequestedList.size(); 469 } 470 } 471 } 472 473 protected static class SatelliteProvisionStateCallbackTest implements 474 SatelliteProvisionStateCallback { 475 public boolean isProvisioned = false; 476 private List<Boolean> mProvisionedStates = new ArrayList<>(); 477 private final Object mProvisionedStatesLock = new Object(); 478 private final Semaphore mSemaphore = new Semaphore(0); 479 480 @Override onSatelliteProvisionStateChanged(boolean provisioned)481 public void onSatelliteProvisionStateChanged(boolean provisioned) { 482 logd("onSatelliteProvisionStateChanged: provisioned=" + provisioned); 483 isProvisioned = provisioned; 484 synchronized (mProvisionedStatesLock) { 485 mProvisionedStates.add(provisioned); 486 } 487 try { 488 mSemaphore.release(); 489 } catch (Exception ex) { 490 loge("onSatelliteProvisionStateChanged: Got exception, ex=" + ex); 491 } 492 } 493 waitUntilResult(int expectedNumberOfEvents)494 public boolean waitUntilResult(int expectedNumberOfEvents) { 495 for (int i = 0; i < expectedNumberOfEvents; i++) { 496 try { 497 if (!mSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) { 498 loge("Timeout to receive onSatelliteProvisionStateChanged"); 499 return false; 500 } 501 } catch (Exception ex) { 502 loge("onSatelliteProvisionStateChanged: Got exception=" + ex); 503 return false; 504 } 505 } 506 return true; 507 } 508 clearProvisionedStates()509 public void clearProvisionedStates() { 510 synchronized (mProvisionedStatesLock) { 511 mProvisionedStates.clear(); 512 mSemaphore.drainPermits(); 513 } 514 } 515 getTotalCountOfProvisionedStates()516 public int getTotalCountOfProvisionedStates() { 517 synchronized (mProvisionedStatesLock) { 518 return mProvisionedStates.size(); 519 } 520 } 521 getProvisionedState(int index)522 public boolean getProvisionedState(int index) { 523 synchronized (mProvisionedStatesLock) { 524 if (index < mProvisionedStates.size()) { 525 return mProvisionedStates.get(index); 526 } 527 } 528 loge("getProvisionedState: invalid index=" + index); 529 return false; 530 } 531 } 532 533 protected static class SatelliteSubscriptionProvisionStateChangedTest implements 534 SatelliteProvisionStateCallback { 535 private List<SatelliteSubscriberProvisionStatus> mResultList = new ArrayList<>(); 536 private final Object mProvisionedStatesLock = new Object(); 537 private final Semaphore mSemaphore = new Semaphore(0); 538 539 @Override onSatelliteProvisionStateChanged(boolean provisioned)540 public void onSatelliteProvisionStateChanged(boolean provisioned) { 541 logd("onSatelliteProvisionStateChanged: provisioned=" + provisioned); 542 } 543 544 @Override onSatelliteSubscriptionProvisionStateChanged( List<SatelliteSubscriberProvisionStatus> list)545 public void onSatelliteSubscriptionProvisionStateChanged( 546 List<SatelliteSubscriberProvisionStatus> list) { 547 logd("onSatelliteSubscriptionProvisionStateChanged:" + list); 548 synchronized (mProvisionedStatesLock) { 549 mResultList = list; 550 } 551 try { 552 mSemaphore.release(); 553 } catch (Exception ex) { 554 loge("onSatelliteSubscriptionProvisionStateChanged: Got exception, ex=" + ex); 555 } 556 } 557 waitUntilResult(int expectedNumberOfEvents)558 public boolean waitUntilResult(int expectedNumberOfEvents) { 559 for (int i = 0; i < expectedNumberOfEvents; i++) { 560 try { 561 if (!mSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) { 562 loge("Timeout to receive onSatelliteSubscriptionProvisionStateChanged"); 563 return false; 564 } 565 } catch (Exception ex) { 566 loge("onSatelliteSubscriptionProvisionStateChanged: Got exception=" + ex); 567 return false; 568 } 569 } 570 return true; 571 } 572 clearProvisionedStates()573 public void clearProvisionedStates() { 574 synchronized (mProvisionedStatesLock) { 575 mResultList.clear(); 576 mSemaphore.drainPermits(); 577 } 578 } 579 getResultList()580 public List<SatelliteSubscriberProvisionStatus> getResultList() { 581 synchronized (mProvisionedStatesLock) { 582 return mResultList; 583 } 584 } 585 } 586 587 protected static class SatelliteModemStateCallbackTest implements SatelliteModemStateCallback { 588 public int modemState = SatelliteManager.SATELLITE_MODEM_STATE_OFF; 589 private List<Integer> mModemStates = new ArrayList<>(); 590 private final Object mModemStatesLock = new Object(); 591 private final Semaphore mSemaphore = new Semaphore(0); 592 private final Semaphore mModemOffSemaphore = new Semaphore(0); 593 594 @Override onSatelliteModemStateChanged(int state)595 public void onSatelliteModemStateChanged(int state) { 596 Log.d(TAG, "onSatelliteModemStateChanged: state=" + state); 597 modemState = state; 598 synchronized (mModemStatesLock) { 599 mModemStates.add(state); 600 } 601 try { 602 mSemaphore.release(); 603 } catch (Exception ex) { 604 Log.e(TAG, "onSatelliteModemStateChanged: Got exception, ex=" + ex); 605 } 606 607 if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) { 608 try { 609 mModemOffSemaphore.release(); 610 } catch (Exception ex) { 611 Log.e(TAG, "onSatelliteModemStateChanged: Got exception in " 612 + "releasing mModemOffSemaphore, ex=" + ex); 613 } 614 } 615 } 616 waitUntilResult(int expectedNumberOfEvents)617 public boolean waitUntilResult(int expectedNumberOfEvents) { 618 for (int i = 0; i < expectedNumberOfEvents; i++) { 619 try { 620 if (!mSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) { 621 Log.e(TAG, "Timeout to receive onSatelliteModemStateChanged"); 622 return false; 623 } 624 } catch (Exception ex) { 625 Log.e(TAG, "onSatelliteModemStateChanged: Got exception=" + ex); 626 return false; 627 } 628 } 629 return true; 630 } 631 waitUntilModemOff()632 public boolean waitUntilModemOff() { 633 try { 634 if (!mModemOffSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) { 635 Log.e(TAG, "Timeout to receive satellite modem off event"); 636 return false; 637 } 638 } catch (Exception ex) { 639 Log.e(TAG, "Waiting for satellite modem off event: Got exception=" + ex); 640 return false; 641 } 642 return true; 643 } 644 waitUntilModemOff(long timeoutMillis)645 public boolean waitUntilModemOff(long timeoutMillis) { 646 try { 647 if (!mModemOffSemaphore.tryAcquire(timeoutMillis, TimeUnit.MILLISECONDS)) { 648 Log.e(TAG, "Timeout to receive satellite modem off event"); 649 return false; 650 } 651 } catch (Exception ex) { 652 Log.e(TAG, "Waiting for satellite modem off event: Got exception=" + ex); 653 return false; 654 } 655 return true; 656 } 657 clearModemStates()658 public void clearModemStates() { 659 synchronized (mModemStatesLock) { 660 Log.d(TAG, "onSatelliteModemStateChanged: clearModemStates"); 661 mModemStates.clear(); 662 mSemaphore.drainPermits(); 663 mModemOffSemaphore.drainPermits(); 664 } 665 } 666 getModemState(int index)667 public int getModemState(int index) { 668 synchronized (mModemStatesLock) { 669 if (index < mModemStates.size()) { 670 return mModemStates.get(index); 671 } else { 672 Log.e(TAG, "getModemState: invalid index=" + index 673 + ", mModemStates.size=" + mModemStates.size()); 674 return -1; 675 } 676 } 677 } 678 getTotalCountOfModemStates()679 public int getTotalCountOfModemStates() { 680 synchronized (mModemStatesLock) { 681 return mModemStates.size(); 682 } 683 } 684 } 685 686 protected static class SatelliteDatagramCallbackTest implements SatelliteDatagramCallback { 687 public SatelliteDatagram mDatagram; 688 public final List<SatelliteDatagram> mDatagramList = new ArrayList<>(); 689 public long mDatagramId; 690 private final Semaphore mSemaphore = new Semaphore(0); 691 692 @Override onSatelliteDatagramReceived(long datagramId, SatelliteDatagram datagram, int pendingCount, Consumer<Void> callback)693 public void onSatelliteDatagramReceived(long datagramId, SatelliteDatagram datagram, 694 int pendingCount, Consumer<Void> callback) { 695 logd("onSatelliteDatagramReceived: datagramId=" + datagramId + ", datagram=" 696 + datagram + ", pendingCount=" + pendingCount); 697 mDatagram = datagram; 698 mDatagramList.add(datagram); 699 mDatagramId = datagramId; 700 if (callback != null) { 701 logd("onSatelliteDatagramReceived: callback.accept() datagramId=" + datagramId); 702 callback.accept(null); 703 } else { 704 logd("onSatelliteDatagramReceived: callback is null datagramId=" + datagramId); 705 } 706 707 try { 708 mSemaphore.release(); 709 } catch (Exception e) { 710 loge("onSatelliteDatagramReceived: Got exception, ex=" + e); 711 } 712 } 713 waitUntilResult(int expectedNumberOfEvents)714 public boolean waitUntilResult(int expectedNumberOfEvents) { 715 for (int i = 0; i < expectedNumberOfEvents; i++) { 716 try { 717 if (!mSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) { 718 loge("Timeout to receive onSatelliteDatagramReceived"); 719 return false; 720 } 721 } catch (Exception ex) { 722 loge("onSatelliteDatagramReceived: Got exception=" + ex); 723 return false; 724 } 725 } 726 return true; 727 } 728 } 729 730 protected static class NtnSignalStrengthCallbackTest implements NtnSignalStrengthCallback { 731 public NtnSignalStrength mNtnSignalStrength; 732 private final Semaphore mSemaphore = new Semaphore(0); 733 734 @Override onNtnSignalStrengthChanged(@onNull NtnSignalStrength ntnSignalStrength)735 public void onNtnSignalStrengthChanged(@NonNull NtnSignalStrength ntnSignalStrength) { 736 logd("onNtnSignalStrengthChanged: ntnSignalStrength=" + ntnSignalStrength); 737 mNtnSignalStrength = new NtnSignalStrength(ntnSignalStrength); 738 739 try { 740 mSemaphore.release(); 741 } catch (Exception e) { 742 loge("onNtnSignalStrengthChanged: Got exception, ex=" + e); 743 } 744 } 745 waitUntilResult(int expectedNumberOfEvents)746 public boolean waitUntilResult(int expectedNumberOfEvents) { 747 for (int i = 0; i < expectedNumberOfEvents; i++) { 748 try { 749 if (!mSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) { 750 loge("Timeout to receive onNtnSignalStrengthChanged"); 751 return false; 752 } 753 } catch (Exception ex) { 754 loge("onNtnSignalStrengthChanged: Got exception=" + ex); 755 return false; 756 } 757 } 758 return true; 759 } 760 drainPermits()761 public void drainPermits() { 762 mSemaphore.drainPermits(); 763 } 764 } 765 766 protected static class SatelliteCapabilitiesCallbackTest implements 767 SatelliteCapabilitiesCallback { 768 public SatelliteCapabilities mSatelliteCapabilities; 769 private final Semaphore mSemaphore = new Semaphore(0); 770 771 @Override onSatelliteCapabilitiesChanged( @onNull SatelliteCapabilities satelliteCapabilities)772 public void onSatelliteCapabilitiesChanged( 773 @NonNull SatelliteCapabilities satelliteCapabilities) { 774 logd("onSatelliteCapabilitiesChanged: satelliteCapabilities=" + satelliteCapabilities); 775 mSatelliteCapabilities = satelliteCapabilities; 776 777 try { 778 mSemaphore.release(); 779 } catch (Exception e) { 780 loge("onSatelliteCapabilitiesChanged: Got exception, ex=" + e); 781 } 782 } 783 waitUntilResult(int expectedNumberOfEvents)784 public boolean waitUntilResult(int expectedNumberOfEvents) { 785 for (int i = 0; i < expectedNumberOfEvents; i++) { 786 try { 787 if (!mSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) { 788 loge("Timeout to receive onSatelliteCapabilitiesChanged"); 789 return false; 790 } 791 } catch (Exception ex) { 792 loge("onSatelliteCapabilitiesChanged: Got exception=" + ex); 793 return false; 794 } 795 } 796 return true; 797 } 798 } 799 800 protected static class SelectedNbIotSatelliteSubscriptionCallbackTest implements 801 SelectedNbIotSatelliteSubscriptionCallback { 802 public int mSelectedSubId; 803 private final Semaphore mSemaphore = new Semaphore(0); 804 805 @Override onSelectedNbIotSatelliteSubscriptionChanged(int selectedSubId)806 public void onSelectedNbIotSatelliteSubscriptionChanged(int selectedSubId) { 807 logd("onSelectedNbIotSatelliteSubscriptionChanged: selectedSubId=" + selectedSubId); 808 mSelectedSubId = selectedSubId; 809 810 try { 811 mSemaphore.release(); 812 } catch (Exception e) { 813 loge("onSelectedNbIotSatelliteSubscriptionChanged: Got exception, ex=" + e); 814 } 815 } 816 waitUntilResult(int expectedNumberOfEvents)817 public boolean waitUntilResult(int expectedNumberOfEvents) { 818 for (int i = 0; i < expectedNumberOfEvents; i++) { 819 try { 820 if (!mSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) { 821 loge("Timeout to receive onSelectedNbIotSatelliteSubscriptionChanged"); 822 return false; 823 } 824 } catch (Exception ex) { 825 loge("onSelectedNbIotSatelliteSubscriptionChanged: Got exception=" + ex); 826 return false; 827 } 828 } 829 return true; 830 } 831 drainPermits()832 public void drainPermits() { 833 mSemaphore.drainPermits(); 834 } 835 } 836 837 protected static class SatelliteSupportedStateCallbackTest implements Consumer<Boolean> { 838 public boolean isSupported = false; 839 private List<Boolean> mSupportedStates = new ArrayList<>(); 840 private final Object mSupportedStatesLock = new Object(); 841 private final Semaphore mSemaphore = new Semaphore(0); 842 843 @Override accept(Boolean supported)844 public void accept(Boolean supported) { 845 logd("onSatelliteSupportedStateChanged: supported=" + supported); 846 isSupported = supported; 847 synchronized (mSupportedStatesLock) { 848 mSupportedStates.add(supported); 849 } 850 try { 851 mSemaphore.release(); 852 } catch (Exception ex) { 853 loge("onSatelliteSupportedStateChanged: Got exception, ex=" + ex); 854 } 855 } 856 waitUntilResult(int expectedNumberOfEvents)857 public boolean waitUntilResult(int expectedNumberOfEvents) { 858 for (int i = 0; i < expectedNumberOfEvents; i++) { 859 try { 860 if (!mSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) { 861 loge("Timeout to receive onSatelliteSupportedStateChanged"); 862 return false; 863 } 864 } catch (Exception ex) { 865 loge("onSatelliteSupportedStateChanged: Got exception=" + ex); 866 return false; 867 } 868 } 869 return true; 870 } 871 clearSupportedStates()872 public void clearSupportedStates() { 873 synchronized (mSupportedStatesLock) { 874 mSupportedStates.clear(); 875 mSemaphore.drainPermits(); 876 } 877 } 878 getTotalCountOfSupportedStates()879 public int getTotalCountOfSupportedStates() { 880 synchronized (mSupportedStatesLock) { 881 return mSupportedStates.size(); 882 } 883 } 884 getSupportedState(int index)885 public Boolean getSupportedState(int index) { 886 synchronized (mSupportedStatesLock) { 887 if (index < mSupportedStates.size()) { 888 return mSupportedStates.get(index); 889 } 890 } 891 loge("getSupportedState: invalid index=" + index); 892 return null; 893 } 894 } 895 896 protected static class SatelliteCommunicationAccessStateCallbackTest 897 implements SatelliteCommunicationAccessStateCallback { 898 public boolean isAllowed = false; 899 @Nullable 900 private SatelliteAccessConfiguration mSatelliteAccessConfiguration; 901 private final Semaphore mSemaphore = new Semaphore(0); 902 private final Semaphore mSatelliteAccessConfigurationChangedSemaphore = new Semaphore(0); 903 904 @Override onAccessAllowedStateChanged(boolean allowed)905 public void onAccessAllowedStateChanged(boolean allowed) { 906 logd("onAccessAllowedStateChanged: isAllowed=" + allowed); 907 isAllowed = allowed; 908 909 try { 910 mSemaphore.release(); 911 } catch (Exception e) { 912 loge("onAccessAllowedStateChanged: Got exception, ex=" + e); 913 } 914 } 915 916 @Override onAccessConfigurationChanged( @ullable SatelliteAccessConfiguration satelliteAccessConfiguration)917 public void onAccessConfigurationChanged( 918 @Nullable SatelliteAccessConfiguration satelliteAccessConfiguration) { 919 logd( 920 "onAccessConfigurationChanged: satelliteAccessConfiguration=" 921 + satelliteAccessConfiguration); 922 mSatelliteAccessConfiguration = satelliteAccessConfiguration; 923 924 try { 925 mSatelliteAccessConfigurationChangedSemaphore.release(); 926 } catch (Exception e) { 927 loge("onAccessConfigurationChanged: Got exception, ex=" + e); 928 } 929 } 930 waitUntilResult(int expectedNumberOfEvents)931 public boolean waitUntilResult(int expectedNumberOfEvents) { 932 for (int i = 0; i < expectedNumberOfEvents; i++) { 933 try { 934 if (!mSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) { 935 loge("Timeout to receive onAccessAllowedStateChanged"); 936 return false; 937 } 938 } catch (Exception ex) { 939 loge("onAccessAllowedStateChanged: Got exception=" + ex); 940 return false; 941 } 942 } 943 return true; 944 } 945 waitUntilSatelliteAccessConfigurationChangedEvent( int expectedNumberOfEvents, long timeOutMilliSec)946 public boolean waitUntilSatelliteAccessConfigurationChangedEvent( 947 int expectedNumberOfEvents, long timeOutMilliSec) { 948 logd("waitUntilSatelliteAccessConfigurationChangedEvent"); 949 for (int i = 0; i < expectedNumberOfEvents; i++) { 950 try { 951 if (!mSatelliteAccessConfigurationChangedSemaphore.tryAcquire(timeOutMilliSec, 952 TimeUnit.MILLISECONDS)) { 953 loge("Timeout to receive " 954 + "waitUntilSatelliteAccessConfigurationChangedEvent"); 955 return false; 956 } 957 } catch (Exception ex) { 958 loge("waitUntilSatelliteAccessConfigurationChangedEvent: Got exception=" + ex); 959 return false; 960 } 961 } 962 return true; 963 } 964 drainPermits()965 public void drainPermits() { 966 mSemaphore.drainPermits(); 967 mSatelliteAccessConfigurationChangedSemaphore.drainPermits(); 968 } 969 970 @Nullable getSatelliteAccessConfiguration()971 public SatelliteAccessConfiguration getSatelliteAccessConfiguration() { 972 return mSatelliteAccessConfiguration; 973 } 974 } 975 976 protected static class SatelliteDisallowedReasonsCallbackTest 977 implements SatelliteDisallowedReasonsCallback { 978 private int[] mSatelliteDisabledReasons; 979 private final Semaphore mSemaphore = new Semaphore(0); 980 981 @Override onSatelliteDisallowedReasonsChanged(@onNull int[] disallowedReasons)982 public void onSatelliteDisallowedReasonsChanged(@NonNull int[] disallowedReasons) { 983 logd("onSatelliteDisallowedReasonsChanged: disallowedReasons=" 984 + Arrays.toString(disallowedReasons)); 985 mSatelliteDisabledReasons = disallowedReasons; 986 try { 987 mSemaphore.release(); 988 } catch (Exception e) { 989 loge("onSatelliteDisallowedReasonsChanged: Got exception, ex=" + e); 990 } 991 } 992 waitUntilResult(int expectedNumberOfEvents)993 public boolean waitUntilResult(int expectedNumberOfEvents) { 994 for (int i = 0; i < expectedNumberOfEvents; i++) { 995 try { 996 if (!mSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) { 997 loge("Timeout to receive onSatelliteDisallowedReasonsChanged"); 998 return false; 999 } 1000 } catch (Exception ex) { 1001 loge("onSatelliteDisallowedReasonsChanged: Got exception=" + ex); 1002 return false; 1003 } 1004 } 1005 return true; 1006 } 1007 drainPermits()1008 public void drainPermits() { 1009 mSemaphore.drainPermits(); 1010 } 1011 hasSatelliteDisabledReason(int reason)1012 public boolean hasSatelliteDisabledReason(int reason) { 1013 return Arrays.stream(mSatelliteDisabledReasons).anyMatch(i -> i == reason); 1014 } 1015 } 1016 1017 protected static class SatelliteModeRadiosUpdater extends ContentObserver implements 1018 AutoCloseable { 1019 private final Context mContext; 1020 private final Semaphore mSemaphore = new Semaphore(0); 1021 private String mExpectedSatelliteModeRadios = ""; 1022 private final Object mLock = new Object(); 1023 SatelliteModeRadiosUpdater(Context context)1024 public SatelliteModeRadiosUpdater(Context context) { 1025 super(new Handler(Looper.getMainLooper())); 1026 mContext = context; 1027 mContext.getContentResolver().registerContentObserver( 1028 Settings.Global.getUriFor(Settings.Global.SATELLITE_MODE_RADIOS), false, this); 1029 InstrumentationRegistry.getInstrumentation().getUiAutomation() 1030 .adoptShellPermissionIdentity(Manifest.permission.SATELLITE_COMMUNICATION, 1031 Manifest.permission.WRITE_SECURE_SETTINGS, 1032 Manifest.permission.NETWORK_SETTINGS, 1033 Manifest.permission.ACCESS_FINE_LOCATION, 1034 Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 1035 Manifest.permission.UWB_PRIVILEGED); 1036 } 1037 1038 @Override onChange(boolean selfChange)1039 public void onChange(boolean selfChange) { 1040 String newSatelliteModeRadios = Settings.Global.getString( 1041 mContext.getContentResolver(), Settings.Global.SATELLITE_MODE_RADIOS); 1042 synchronized (mLock) { 1043 if (TextUtils.equals(mExpectedSatelliteModeRadios, newSatelliteModeRadios)) { 1044 logd("SatelliteModeRadiosUpdater: onChange, newSatelliteModeRadios=" 1045 + newSatelliteModeRadios); 1046 try { 1047 mSemaphore.release(); 1048 } catch (Exception ex) { 1049 loge("SatelliteModeRadiosUpdater: onChange, ex=" + ex); 1050 } 1051 } 1052 } 1053 } 1054 1055 @Override close()1056 public void close() throws Exception { 1057 mContext.getContentResolver().unregisterContentObserver(this); 1058 InstrumentationRegistry.getInstrumentation().getUiAutomation() 1059 .dropShellPermissionIdentity(); 1060 } 1061 setSatelliteModeRadios(String expectedSatelliteModeRadios)1062 public boolean setSatelliteModeRadios(String expectedSatelliteModeRadios) { 1063 logd("setSatelliteModeRadios: expectedSatelliteModeRadios=" 1064 + expectedSatelliteModeRadios); 1065 String originalSatelliteModeRadios = Settings.Global.getString( 1066 mContext.getContentResolver(), Settings.Global.SATELLITE_MODE_RADIOS); 1067 if (TextUtils.equals(expectedSatelliteModeRadios, originalSatelliteModeRadios)) { 1068 logd("setSatelliteModeRadios: satellite radios mode is already as expected"); 1069 return true; 1070 } 1071 1072 setExpectedSatelliteModeRadios(expectedSatelliteModeRadios); 1073 clearSemaphorePermits(); 1074 Settings.Global.putString(mContext.getContentResolver(), 1075 Settings.Global.SATELLITE_MODE_RADIOS, expectedSatelliteModeRadios); 1076 return waitForModeChanged(); 1077 } 1078 clearSemaphorePermits()1079 private void clearSemaphorePermits() { 1080 mSemaphore.drainPermits(); 1081 } 1082 waitForModeChanged()1083 private boolean waitForModeChanged() { 1084 logd("SatelliteModeRadiosUpdater: waitForModeChanged start"); 1085 try { 1086 if (!mSemaphore.tryAcquire(EXTERNAL_DEPENDENT_TIMEOUT, TimeUnit.MILLISECONDS)) { 1087 loge("SatelliteModeRadiosUpdater: Timeout to wait for mode changed"); 1088 return false; 1089 } 1090 } catch (InterruptedException e) { 1091 loge("SatelliteModeRadiosUpdater: waitForModeChanged, e=" + e); 1092 return false; 1093 } 1094 return true; 1095 } 1096 setExpectedSatelliteModeRadios(String expectedSatelliteModeRadios)1097 private void setExpectedSatelliteModeRadios(String expectedSatelliteModeRadios) { 1098 synchronized (mLock) { 1099 mExpectedSatelliteModeRadios = expectedSatelliteModeRadios; 1100 } 1101 logd("SatelliteModeRadiosUpdater: mExpectedSatelliteModeRadios=" 1102 + mExpectedSatelliteModeRadios); 1103 } 1104 } 1105 provisionSatellite()1106 protected static boolean provisionSatellite() { 1107 LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1); 1108 String mText = "This is test provision data."; 1109 byte[] testProvisionData = mText.getBytes(); 1110 1111 sSatelliteManager.provisionService( 1112 TOKEN, testProvisionData, null, getContext().getMainExecutor(), error::offer); 1113 Integer errorCode; 1114 try { 1115 errorCode = error.poll(TIMEOUT, TimeUnit.MILLISECONDS); 1116 } catch (InterruptedException ex) { 1117 loge("provisionSatellite ex=" + ex); 1118 return false; 1119 } 1120 if (errorCode == null || errorCode != SatelliteManager.SATELLITE_RESULT_SUCCESS) { 1121 loge("provisionSatellite failed with errorCode=" + errorCode); 1122 return false; 1123 } 1124 return true; 1125 } 1126 deprovisionSatellite()1127 protected static boolean deprovisionSatellite() { 1128 LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1); 1129 1130 sSatelliteManager.deprovisionService( 1131 TOKEN, getContext().getMainExecutor(), error::offer); 1132 Integer errorCode; 1133 try { 1134 errorCode = error.poll(TIMEOUT, TimeUnit.MILLISECONDS); 1135 } catch (InterruptedException ex) { 1136 loge("deprovisionSatellite ex=" + ex); 1137 return false; 1138 } 1139 if (errorCode == null || errorCode != SatelliteManager.SATELLITE_RESULT_SUCCESS) { 1140 loge("deprovisionSatellite failed with errorCode=" + errorCode); 1141 return false; 1142 } 1143 return true; 1144 } 1145 isSatelliteProvisioned()1146 protected static boolean isSatelliteProvisioned() { 1147 final AtomicReference<Boolean> provisioned = new AtomicReference<>(); 1148 final AtomicReference<Integer> errorCode = new AtomicReference<>(); 1149 CountDownLatch latch = new CountDownLatch(1); 1150 OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> receiver = 1151 new OutcomeReceiver<>() { 1152 @Override 1153 public void onResult(Boolean result) { 1154 logd("isSatelliteProvisioned: result=" + result); 1155 provisioned.set(result); 1156 latch.countDown(); 1157 } 1158 1159 @Override 1160 public void onError(SatelliteManager.SatelliteException exception) { 1161 logd("isSatelliteProvisioned: onError, exception=" + exception); 1162 errorCode.set(exception.getErrorCode()); 1163 latch.countDown(); 1164 } 1165 }; 1166 1167 sSatelliteManager.requestIsProvisioned( 1168 getContext().getMainExecutor(), receiver); 1169 try { 1170 assertTrue(latch.await(TIMEOUT, TimeUnit.MILLISECONDS)); 1171 } catch (InterruptedException ex) { 1172 loge("isSatelliteProvisioned ex=" + ex); 1173 return false; 1174 } 1175 1176 Integer error = errorCode.get(); 1177 Boolean isProvisioned = provisioned.get(); 1178 if (error == null) { 1179 logd("isSatelliteProvisioned isProvisioned=" + isProvisioned); 1180 assertNotNull(isProvisioned); 1181 return isProvisioned; 1182 } else { 1183 assertNull(isProvisioned); 1184 logd("isSatelliteProvisioned error=" + error); 1185 return false; 1186 } 1187 } 1188 isSatelliteEnabled()1189 protected static boolean isSatelliteEnabled() { 1190 logd("isSatelliteEnabled"); 1191 1192 final AtomicReference<Boolean> enabled = new AtomicReference<>(); 1193 final AtomicReference<Integer> errorCode = new AtomicReference<>(); 1194 CountDownLatch latch = new CountDownLatch(1); 1195 OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> receiver = 1196 new OutcomeReceiver<>() { 1197 @Override 1198 public void onResult(Boolean result) { 1199 logd("isSatelliteEnabled: satellite enablement result: " + result); 1200 enabled.set(result); 1201 latch.countDown(); 1202 } 1203 1204 @Override 1205 public void onError(SatelliteManager.SatelliteException exception) { 1206 logd( 1207 "isSatelliteEnabled: satellite enablement error: " 1208 + exception.getErrorCode()); 1209 errorCode.set(exception.getErrorCode()); 1210 latch.countDown(); 1211 } 1212 }; 1213 1214 logd("isSatelliteEnabled: querying satellite enable state"); 1215 sSatelliteManager.requestIsEnabled( 1216 getContext().getMainExecutor(), receiver); 1217 try { 1218 assertTrue(latch.await(TIMEOUT, TimeUnit.MILLISECONDS)); 1219 } catch (InterruptedException ex) { 1220 loge("isSatelliteEnabled ex=" + ex); 1221 return false; 1222 } 1223 1224 Integer error = errorCode.get(); 1225 Boolean isEnabled = enabled.get(); 1226 if (error == null) { 1227 assertNotNull(isEnabled); 1228 return isEnabled; 1229 } else { 1230 assertNull(isEnabled); 1231 logd("isSatelliteEnabled error=" + error); 1232 return false; 1233 } 1234 } 1235 isSatelliteDemoModeEnabled()1236 protected static boolean isSatelliteDemoModeEnabled() { 1237 final AtomicReference<Boolean> enabled = new AtomicReference<>(); 1238 final AtomicReference<Integer> errorCode = new AtomicReference<>(); 1239 CountDownLatch latch = new CountDownLatch(1); 1240 OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> receiver = 1241 new OutcomeReceiver<>() { 1242 @Override 1243 public void onResult(Boolean result) { 1244 enabled.set(result); 1245 latch.countDown(); 1246 } 1247 1248 @Override 1249 public void onError(SatelliteManager.SatelliteException exception) { 1250 errorCode.set(exception.getErrorCode()); 1251 latch.countDown(); 1252 } 1253 }; 1254 1255 sSatelliteManager.requestIsDemoModeEnabled( 1256 getContext().getMainExecutor(), receiver); 1257 try { 1258 assertTrue(latch.await(TIMEOUT, TimeUnit.MILLISECONDS)); 1259 } catch (InterruptedException ex) { 1260 loge("isSatelliteDemoModeEnabled ex=" + ex); 1261 return false; 1262 } 1263 1264 Integer error = errorCode.get(); 1265 Boolean isEnabled = enabled.get(); 1266 if (error == null) { 1267 assertNotNull(isEnabled); 1268 return isEnabled; 1269 } else { 1270 assertNull(isEnabled); 1271 logd("isSatelliteEnabled error=" + error); 1272 return false; 1273 } 1274 } 1275 requestSatelliteEnabled(boolean enabled)1276 protected static void requestSatelliteEnabled(boolean enabled) { 1277 logd("requestSatelliteEnabled: enabled=" + enabled); 1278 LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1); 1279 logd( 1280 "requestSatelliteEnabled: requesting satellite to be " 1281 + (enabled ? "enabled" : "disabled")); 1282 sSatelliteManager.requestEnabled(new EnableRequestAttributes.Builder(enabled).build(), 1283 getContext().getMainExecutor(), error::offer); 1284 Integer errorCode; 1285 try { 1286 errorCode = error.poll(TIMEOUT, TimeUnit.MILLISECONDS); 1287 } catch (InterruptedException ex) { 1288 fail("requestSatelliteEnabled failed with ex=" + ex); 1289 return; 1290 } 1291 logd("requestSatelliteEnabled: errorCode=" + errorCode); 1292 assertNotNull(errorCode); 1293 assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS, (long) errorCode); 1294 } 1295 requestSatelliteEnabled(boolean enabled, boolean emergency)1296 protected static void requestSatelliteEnabled(boolean enabled, boolean emergency) { 1297 LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1); 1298 sSatelliteManager.requestEnabled( 1299 new EnableRequestAttributes.Builder(enabled) 1300 .setEmergencyMode(emergency) 1301 .build(), 1302 getContext().getMainExecutor(), error::offer); 1303 Integer errorCode; 1304 try { 1305 errorCode = error.poll(TIMEOUT, TimeUnit.MILLISECONDS); 1306 } catch (InterruptedException ex) { 1307 fail("requestSatelliteEnabled failed with ex=" + ex); 1308 return; 1309 } 1310 logd("requestSatelliteEnabled: errorCode=" + errorCode); 1311 assertNotNull(errorCode); 1312 assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS, (long) errorCode); 1313 } 1314 requestSatelliteEnabled(boolean enabled, long timeoutMillis)1315 protected static void requestSatelliteEnabled(boolean enabled, long timeoutMillis) { 1316 LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1); 1317 sSatelliteManager.requestEnabled(new EnableRequestAttributes.Builder(enabled).build(), 1318 getContext().getMainExecutor(), error::offer); 1319 Integer errorCode; 1320 try { 1321 errorCode = error.poll(timeoutMillis, TimeUnit.MILLISECONDS); 1322 } catch (InterruptedException ex) { 1323 fail("requestSatelliteEnabled failed with ex=" + ex); 1324 return; 1325 } 1326 logd("requestSatelliteEnabled: errorCode=" + errorCode); 1327 assertNotNull(errorCode); 1328 assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS, (long) errorCode); 1329 } 1330 requestSatelliteEnabledWithResult(boolean enabled, long timeoutMillis)1331 protected static int requestSatelliteEnabledWithResult(boolean enabled, long timeoutMillis) { 1332 logd( 1333 "requestSatelliteEnabledWithResult: enabled=" 1334 + enabled 1335 + ", timeoutMillis=" 1336 + timeoutMillis); 1337 LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1); 1338 sSatelliteManager.requestEnabled(new EnableRequestAttributes.Builder(enabled).build(), 1339 getContext().getMainExecutor(), error::offer); 1340 Integer errorCode = null; 1341 try { 1342 errorCode = error.poll(timeoutMillis, TimeUnit.MILLISECONDS); 1343 } catch (InterruptedException ex) { 1344 fail("requestSatelliteEnabled failed with ex=" + ex); 1345 } 1346 logd("requestSatelliteEnabledWithResult: errorCode=" + errorCode); 1347 assertNotNull(errorCode); 1348 return errorCode; 1349 } 1350 requestSatelliteEnabledForDemoMode(boolean enabled)1351 protected static void requestSatelliteEnabledForDemoMode(boolean enabled) { 1352 LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1); 1353 sSatelliteManager.requestEnabled( 1354 new EnableRequestAttributes.Builder(enabled) 1355 .setDemoMode(true) 1356 .setEmergencyMode(true) 1357 .build(), 1358 getContext().getMainExecutor(), error::offer); 1359 Integer errorCode; 1360 try { 1361 errorCode = error.poll(TIMEOUT, TimeUnit.MILLISECONDS); 1362 } catch (InterruptedException ex) { 1363 fail("requestSatelliteEnabled failed with ex=" + ex); 1364 return; 1365 } 1366 logd("requestSatelliteEnabledForDemoMode: errorCode=" + errorCode); 1367 assertNotNull(errorCode); 1368 assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS, (long) errorCode); 1369 } 1370 requestSatelliteEnabled(boolean enabled, boolean demoEnabled, int expectedError)1371 protected static void requestSatelliteEnabled(boolean enabled, boolean demoEnabled, 1372 int expectedError) { 1373 LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1); 1374 sSatelliteManager.requestEnabled( 1375 new EnableRequestAttributes.Builder(enabled).setDemoMode(demoEnabled).build(), 1376 getContext().getMainExecutor(), error::offer); 1377 Integer errorCode; 1378 try { 1379 errorCode = error.poll(TIMEOUT, TimeUnit.MILLISECONDS); 1380 } catch (InterruptedException ex) { 1381 fail("requestSatelliteEnabled failed with ex=" + ex); 1382 return; 1383 } 1384 logd("requestSatelliteEnabled: errorCode=" + errorCode); 1385 assertNotNull(errorCode); 1386 assertEquals(expectedError, (long) errorCode); 1387 } 1388 verifyEmergencyMode(boolean expectedEmergencyMode)1389 protected static void verifyEmergencyMode(boolean expectedEmergencyMode) { 1390 final AtomicReference<Boolean> emergency = new AtomicReference<>(); 1391 final AtomicReference<Integer> errorCode = new AtomicReference<>(); 1392 CountDownLatch latch = new CountDownLatch(1); 1393 OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> receiver = 1394 new OutcomeReceiver<>() { 1395 @Override 1396 public void onResult(Boolean result) { 1397 emergency.set(result); 1398 latch.countDown(); 1399 } 1400 1401 @Override 1402 public void onError(SatelliteManager.SatelliteException exception) { 1403 errorCode.set(exception.getErrorCode()); 1404 latch.countDown(); 1405 } 1406 }; 1407 1408 sSatelliteManager.requestIsEmergencyModeEnabled(getContext().getMainExecutor(), 1409 receiver); 1410 try { 1411 assertTrue(latch.await(TIMEOUT, TimeUnit.MILLISECONDS)); 1412 } catch (InterruptedException ex) { 1413 fail("Got InterruptedException for requestIsEmergencyModeEnabled, ex=" + ex); 1414 } 1415 1416 Integer error = errorCode.get(); 1417 Boolean isEmergency = emergency.get(); 1418 if (error == null) { 1419 logd("verifyEmergencyMode isEmergency=" + isEmergency); 1420 assertNotNull(isEmergency); 1421 assertEquals(expectedEmergencyMode, isEmergency); 1422 } else { 1423 fail("Got error for requestIsEmergencyModeEnabled, error=" + error); 1424 } 1425 } 1426 verifyDemoMode(boolean expectedDemoMode)1427 protected static void verifyDemoMode(boolean expectedDemoMode) { 1428 final AtomicReference<Boolean> demoMode = new AtomicReference<>(); 1429 final AtomicReference<Integer> errorCode = new AtomicReference<>(); 1430 CountDownLatch latch = new CountDownLatch(1); 1431 OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> receiver = 1432 new OutcomeReceiver<>() { 1433 @Override 1434 public void onResult(Boolean result) { 1435 demoMode.set(result); 1436 latch.countDown(); 1437 } 1438 1439 @Override 1440 public void onError(SatelliteManager.SatelliteException exception) { 1441 errorCode.set(exception.getErrorCode()); 1442 latch.countDown(); 1443 } 1444 }; 1445 1446 sSatelliteManager.requestIsDemoModeEnabled(getContext().getMainExecutor(), 1447 receiver); 1448 try { 1449 assertTrue(latch.await(TIMEOUT, TimeUnit.MILLISECONDS)); 1450 } catch (InterruptedException ex) { 1451 fail("Got InterruptedException for requestIsEmergencyModeEnabled, ex=" + ex); 1452 } 1453 1454 Integer error = errorCode.get(); 1455 Boolean isDemoModeEnabled = demoMode.get(); 1456 if (error == null) { 1457 logd("verifyDemoMode isDemoModeEnabled=" + isDemoModeEnabled); 1458 assertNotNull(isDemoModeEnabled); 1459 assertEquals(expectedDemoMode, isDemoModeEnabled); 1460 } else { 1461 fail("Got error for requestIsEmergencyModeEnabled, error=" + error); 1462 } 1463 } 1464 requestSatelliteEnabledWithoutWaitingForResult( boolean enabled, boolean demoMode, boolean emergency)1465 protected static LinkedBlockingQueue<Integer> requestSatelliteEnabledWithoutWaitingForResult( 1466 boolean enabled, boolean demoMode, boolean emergency) { 1467 LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1); 1468 sSatelliteManager.requestEnabled(new EnableRequestAttributes.Builder(enabled) 1469 .setDemoMode(demoMode) 1470 .setEmergencyMode(emergency) 1471 .build(), 1472 getContext().getMainExecutor(), error::offer); 1473 return error; 1474 } 1475 assertResult(LinkedBlockingQueue<Integer> result, int expectedError)1476 protected static void assertResult(LinkedBlockingQueue<Integer> result, int expectedError) { 1477 Integer errorCode; 1478 try { 1479 errorCode = result.poll(TIMEOUT, TimeUnit.MILLISECONDS); 1480 } catch (InterruptedException ex) { 1481 fail("assertResult failed with ex=" + ex); 1482 return; 1483 } 1484 logd("assertResult: errorCode=" + errorCode); 1485 assertNotNull(errorCode); 1486 assertEquals(expectedError, (long) errorCode); 1487 } 1488 isSatelliteSupported()1489 protected static boolean isSatelliteSupported() { 1490 final AtomicReference<Boolean> supported = new AtomicReference<>(); 1491 final AtomicReference<Integer> errorCode = new AtomicReference<>(); 1492 CountDownLatch latch = new CountDownLatch(1); 1493 OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> receiver = 1494 new OutcomeReceiver<>() { 1495 @Override 1496 public void onResult(Boolean result) { 1497 supported.set(result); 1498 latch.countDown(); 1499 } 1500 1501 @Override 1502 public void onError(SatelliteManager.SatelliteException exception) { 1503 errorCode.set(exception.getErrorCode()); 1504 latch.countDown(); 1505 } 1506 }; 1507 1508 sSatelliteManager.requestIsSupported(getContext().getMainExecutor(), 1509 receiver); 1510 try { 1511 assertTrue(latch.await(TIMEOUT, TimeUnit.MILLISECONDS)); 1512 } catch (InterruptedException ex) { 1513 loge("isSatelliteSupported ex=" + ex); 1514 return false; 1515 } 1516 1517 Integer error = errorCode.get(); 1518 Boolean isSupported = supported.get(); 1519 if (error == null) { 1520 assertNotNull(isSupported); 1521 logd("isSatelliteSupported isSupported=" + isSupported); 1522 return isSupported; 1523 } else { 1524 assertNull(isSupported); 1525 logd("isSatelliteSupported error=" + error); 1526 return false; 1527 } 1528 } 1529 turnRadioOff()1530 protected static void turnRadioOff() { 1531 ServiceStateRadioStateListener callback = new ServiceStateRadioStateListener( 1532 sTelephonyManager.getServiceState(), sTelephonyManager.getRadioPowerState()); 1533 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(sTelephonyManager, 1534 tm -> tm.registerTelephonyCallback(Runnable::run, callback)); 1535 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(sTelephonyManager, 1536 tm -> tm.requestRadioPowerOffForReason(TelephonyManager.RADIO_POWER_REASON_USER), 1537 android.Manifest.permission.MODIFY_PHONE_STATE); 1538 callback.waitForRadioStateIntent(TelephonyManager.RADIO_POWER_OFF); 1539 } 1540 turnRadioOn()1541 protected static void turnRadioOn() { 1542 ServiceStateRadioStateListener callback = new ServiceStateRadioStateListener( 1543 sTelephonyManager.getServiceState(), sTelephonyManager.getRadioPowerState()); 1544 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(sTelephonyManager, 1545 tm -> tm.registerTelephonyCallback(Runnable::run, callback)); 1546 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(sTelephonyManager, 1547 tm -> tm.clearRadioPowerOffForReason(TelephonyManager.RADIO_POWER_REASON_USER), 1548 android.Manifest.permission.MODIFY_PHONE_STATE); 1549 callback.waitForRadioStateIntent(TelephonyManager.RADIO_POWER_ON); 1550 } 1551 1552 protected class UwbAdapterStateCallback implements UwbManager.AdapterStateCallback { 1553 private final Semaphore mUwbSemaphore = new Semaphore(0); 1554 private final Object mUwbExpectedStateLock = new Object(); 1555 private boolean mUwbExpectedState = false; 1556 toString(int state)1557 public String toString(int state) { 1558 switch (state) { 1559 case UwbManager.AdapterStateCallback.STATE_DISABLED: 1560 return "Disabled"; 1561 1562 case UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE: 1563 return "Inactive"; 1564 1565 case UwbManager.AdapterStateCallback.STATE_ENABLED_ACTIVE: 1566 return "Active"; 1567 1568 default: 1569 return ""; 1570 } 1571 } 1572 1573 @Override onStateChanged(int state, int reason)1574 public void onStateChanged(int state, int reason) { 1575 logd("UwbAdapterStateCallback onStateChanged() called, state = " + toString(state)); 1576 logd("Adapter state changed reason " + String.valueOf(reason)); 1577 1578 synchronized (mUwbExpectedStateLock) { 1579 if (mUwbExpectedState == mUwbManager.isUwbEnabled()) { 1580 try { 1581 mUwbSemaphore.release(); 1582 } catch (Exception e) { 1583 loge("UwbAdapterStateCallback onStateChanged(): Got exception, ex=" + e); 1584 } 1585 } 1586 } 1587 } 1588 waitUntilOnUwbStateChanged()1589 public boolean waitUntilOnUwbStateChanged() { 1590 synchronized (mUwbExpectedStateLock) { 1591 if (mUwbExpectedState == mUwbManager.isUwbEnabled()) { 1592 return true; 1593 } 1594 } 1595 1596 try { 1597 if (!mUwbSemaphore.tryAcquire(EXTERNAL_DEPENDENT_TIMEOUT, 1598 TimeUnit.MILLISECONDS)) { 1599 loge("UwbAdapterStateCallback Timeout to receive " 1600 + "onStateChanged() callback"); 1601 return false; 1602 } 1603 } catch (Exception ex) { 1604 loge("UwbAdapterStateCallback waitUntilOnUwbStateChanged: Got exception=" + ex); 1605 return false; 1606 } 1607 return true; 1608 } 1609 setUwbExpectedState(boolean expectedState)1610 public void setUwbExpectedState(boolean expectedState) { 1611 synchronized (mUwbExpectedStateLock) { 1612 mUwbExpectedState = expectedState; 1613 mUwbSemaphore.drainPermits(); 1614 } 1615 } 1616 } 1617 1618 protected class BTWifiNFCStateReceiver extends BroadcastReceiver { 1619 private final Semaphore mBTSemaphore = new Semaphore(0); 1620 private final Object mBTExpectedStateLock = new Object(); 1621 private boolean mBTExpectedState = false; 1622 1623 private final Semaphore mNfcSemaphore = new Semaphore(0); 1624 private final Object mNfcExpectedStateLock = new Object(); 1625 private boolean mNfcExpectedState = false; 1626 1627 private final Semaphore mWifiSemaphore = new Semaphore(0); 1628 private final Object mWifiExpectedStateLock = new Object(); 1629 private boolean mWifiExpectedState = false; 1630 1631 @Override onReceive(Context context, Intent intent)1632 public void onReceive(Context context, Intent intent) { 1633 final String action = intent.getAction(); 1634 if (action == null) { 1635 logd("BTWifiNFCStateReceiver NULL action for intent " + intent); 1636 return; 1637 } 1638 logd("BTWifiNFCStateReceiver onReceive: action = " + action); 1639 1640 switch (action) { 1641 case BluetoothAdapter.ACTION_STATE_CHANGED: 1642 int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 1643 BluetoothAdapter.ERROR); 1644 logd("Bluetooth state updated to " + btState); 1645 1646 synchronized (mBTExpectedStateLock) { 1647 if (mBTExpectedState == mBluetoothAdapter.isEnabled()) { 1648 try { 1649 mBTSemaphore.release(); 1650 } catch (Exception e) { 1651 loge("BTWifiNFCStateReceiver onReceive(): Got exception, ex=" + e); 1652 } 1653 } 1654 } 1655 break; 1656 1657 case NfcAdapter.ACTION_ADAPTER_STATE_CHANGED: 1658 int nfcState = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE, -1); 1659 logd("Nfc state updated to " + nfcState); 1660 1661 synchronized (mNfcExpectedStateLock) { 1662 if (mNfcExpectedState == mNfcAdapter.isEnabled()) { 1663 try { 1664 mNfcSemaphore.release(); 1665 } catch (Exception e) { 1666 loge("BTWifiNFCStateReceiver onReceive(): Got exception, ex=" + e); 1667 } 1668 } 1669 } 1670 break; 1671 1672 case WifiManager.WIFI_STATE_CHANGED_ACTION: 1673 int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 1674 WifiManager.WIFI_STATE_UNKNOWN); 1675 logd("Wifi state updated to " + wifiState); 1676 1677 synchronized (mWifiExpectedStateLock) { 1678 if (mWifiExpectedState == mWifiManager.isWifiEnabled()) { 1679 try { 1680 mWifiSemaphore.release(); 1681 } catch (Exception e) { 1682 loge("BTWifiNFCStateReceiver onReceive(): Got exception, ex=" + e); 1683 } 1684 } 1685 } 1686 break; 1687 default: 1688 break; 1689 } 1690 } 1691 waitUntilOnBTStateChanged()1692 public boolean waitUntilOnBTStateChanged() { 1693 logd("waitUntilOnBTStateChanged"); 1694 synchronized (mBTExpectedStateLock) { 1695 if (mBTExpectedState == mBluetoothAdapter.isEnabled()) { 1696 return true; 1697 } 1698 } 1699 1700 try { 1701 if (!mBTSemaphore.tryAcquire(EXTERNAL_DEPENDENT_TIMEOUT, 1702 TimeUnit.MILLISECONDS)) { 1703 loge("BTWifiNFCStateReceiver waitUntilOnBTStateChanged: " 1704 + "Timeout to receive onStateChanged() callback"); 1705 return false; 1706 } 1707 } catch (Exception ex) { 1708 loge("BTWifiNFCStateReceiver waitUntilOnBTStateChanged: Got exception=" + ex); 1709 return false; 1710 } 1711 return true; 1712 } 1713 waitUntilOnNfcStateChanged()1714 public boolean waitUntilOnNfcStateChanged() { 1715 synchronized (mNfcExpectedStateLock) { 1716 if (mNfcExpectedState == mNfcAdapter.isEnabled()) { 1717 return true; 1718 } 1719 } 1720 1721 try { 1722 if (!mNfcSemaphore.tryAcquire(EXTERNAL_DEPENDENT_TIMEOUT, 1723 TimeUnit.MILLISECONDS)) { 1724 loge("BTWifiNFCStateReceiver waitUntilOnNfcStateChanged: " 1725 + "Timeout to receive onStateChanged() callback"); 1726 return false; 1727 } 1728 } catch (Exception ex) { 1729 loge("BTWifiNFCStateReceiver waitUntilOnNfcStateChanged: Got exception=" + ex); 1730 return false; 1731 } 1732 return true; 1733 } 1734 waitUntilOnWifiStateChanged()1735 public boolean waitUntilOnWifiStateChanged() { 1736 synchronized (mWifiExpectedStateLock) { 1737 if (mWifiExpectedState == mWifiManager.isWifiEnabled()) { 1738 return true; 1739 } 1740 } 1741 1742 try { 1743 if (!mWifiSemaphore.tryAcquire(EXTERNAL_DEPENDENT_TIMEOUT, 1744 TimeUnit.MILLISECONDS)) { 1745 loge("BTWifiNFCStateReceiver waitUntilOnWifiStateChanged: " 1746 + "Timeout to receive onStateChanged() callback"); 1747 return false; 1748 } 1749 } catch (Exception ex) { 1750 loge("BTWifiNFCStateReceiver waitUntilOnWifiStateChanged: Got exception=" + ex); 1751 return false; 1752 } 1753 return true; 1754 } 1755 setBTExpectedState(boolean expectedState)1756 public void setBTExpectedState(boolean expectedState) { 1757 synchronized (mBTExpectedStateLock) { 1758 mBTExpectedState = expectedState; 1759 mBTSemaphore.drainPermits(); 1760 } 1761 } 1762 setWifiExpectedState(boolean expectedState)1763 public void setWifiExpectedState(boolean expectedState) { 1764 synchronized (mWifiExpectedStateLock) { 1765 mWifiExpectedState = expectedState; 1766 mWifiSemaphore.drainPermits(); 1767 } 1768 } 1769 setNfcExpectedState(boolean expectedState)1770 public void setNfcExpectedState(boolean expectedState) { 1771 synchronized (mNfcExpectedStateLock) { 1772 mNfcExpectedState = expectedState; 1773 mNfcSemaphore.drainPermits(); 1774 } 1775 } 1776 } 1777 logd(@onNull String log)1778 protected static void logd(@NonNull String log) { 1779 Rlog.d(TAG, log); 1780 } 1781 loge(@onNull String log)1782 protected static void loge(@NonNull String log) { 1783 Rlog.e(TAG, log); 1784 } 1785 assertSatelliteEnabledInSettings(boolean enabled)1786 protected static void assertSatelliteEnabledInSettings(boolean enabled) { 1787 int satelliteModeEnabled = Settings.Global.getInt(getContext().getContentResolver(), 1788 Settings.Global.SATELLITE_MODE_ENABLED, 0); 1789 if (enabled) { 1790 assertEquals(satelliteModeEnabled, 1); 1791 } else { 1792 assertEquals(satelliteModeEnabled, 0); 1793 } 1794 logd("requestSatelliteEnabled: " + enabled 1795 + " : satelliteModeEnabled from settings: " + satelliteModeEnabled); 1796 } 1797 waitFor(long timeoutMillis)1798 protected static void waitFor(long timeoutMillis) { 1799 Object delayTimeout = new Object(); 1800 synchronized (delayTimeout) { 1801 try { 1802 delayTimeout.wait(timeoutMillis); 1803 } catch (InterruptedException ex) { 1804 // Ignore the exception 1805 logd("waitFor: delayTimeout ex=" + ex); 1806 } 1807 } 1808 } 1809 1810 // Get default active subscription ID. getActiveSubIDForCarrierSatelliteTest()1811 protected static int getActiveSubIDForCarrierSatelliteTest() { 1812 Context context = InstrumentationRegistry.getInstrumentation().getContext(); 1813 SubscriptionManager sm = context.getSystemService(SubscriptionManager.class); 1814 List<SubscriptionInfo> infos = ShellIdentityUtils.invokeMethodWithShellPermissions(sm, 1815 SubscriptionManager::getActiveSubscriptionInfoList); 1816 1817 int defaultSubId = SubscriptionManager.getDefaultVoiceSubscriptionId(); 1818 if (defaultSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID 1819 && isSubIdInInfoList(infos, defaultSubId)) { 1820 return defaultSubId; 1821 } 1822 1823 defaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 1824 if (defaultSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID 1825 && isSubIdInInfoList(infos, defaultSubId)) { 1826 return defaultSubId; 1827 } 1828 1829 // Couldn't resolve a default. We can try to resolve a default using the active 1830 // subscriptions. 1831 if (!infos.isEmpty()) { 1832 return infos.get(0).getSubscriptionId(); 1833 } 1834 loge("getActiveSubIDForCarrierSatelliteTest: use invalid subscription ID"); 1835 // There must be at least one active subscription. 1836 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 1837 } 1838 getNtnOnlySubscriptionId()1839 protected static int getNtnOnlySubscriptionId() { 1840 Context context = InstrumentationRegistry.getInstrumentation().getContext(); 1841 SubscriptionManager sm = context.getSystemService(SubscriptionManager.class); 1842 List<SubscriptionInfo> infoList = ShellIdentityUtils.invokeMethodWithShellPermissions(sm, 1843 SubscriptionManager::getAllSubscriptionInfoList); 1844 1845 int subId = infoList.stream() 1846 .filter(info -> info.isOnlyNonTerrestrialNetwork()) 1847 .mapToInt(SubscriptionInfo::getSubscriptionId) 1848 .findFirst() 1849 .orElse(SubscriptionManager.INVALID_SUBSCRIPTION_ID); 1850 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID && !infoList.isEmpty()) { 1851 subId = infoList.get(0).getSubscriptionId(); 1852 } 1853 logd("getNtnOnlySubscriptionId: subId=" + subId); 1854 return subId; 1855 } 1856 isSubIdInInfoList(List<SubscriptionInfo> infos, int subId)1857 private static boolean isSubIdInInfoList(List<SubscriptionInfo> infos, int subId) { 1858 return infos.stream().anyMatch(info -> info.getSubscriptionId() == subId); 1859 } 1860 1861 protected static Pair<List<SatelliteSubscriberProvisionStatus>, Integer> requestSatelliteSubscriberProvisionStatus()1862 requestSatelliteSubscriberProvisionStatus() { 1863 final AtomicReference<List<SatelliteSubscriberProvisionStatus>> list = 1864 new AtomicReference<>(); 1865 final AtomicReference<Integer> errorCode = new AtomicReference<>(); 1866 CountDownLatch latch = new CountDownLatch(1); 1867 OutcomeReceiver<List<SatelliteSubscriberProvisionStatus>, 1868 SatelliteManager.SatelliteException> 1869 receiver = 1870 new OutcomeReceiver<>() { 1871 @Override 1872 public void onResult(List<SatelliteSubscriberProvisionStatus> result) { 1873 list.set(result); 1874 latch.countDown(); 1875 } 1876 1877 @Override 1878 public void onError(SatelliteManager.SatelliteException exception) { 1879 errorCode.set(exception.getErrorCode()); 1880 latch.countDown(); 1881 } 1882 }; 1883 1884 sSatelliteManager.requestSatelliteSubscriberProvisionStatus( 1885 getContext().getMainExecutor(), receiver); 1886 try { 1887 assertTrue(latch.await(TIMEOUT, TimeUnit.MILLISECONDS)); 1888 } catch (InterruptedException ex) { 1889 loge("requestSatelliteSubscriberProvisionStatus ex=" + ex); 1890 return null; 1891 } 1892 1893 Integer error = errorCode.get(); 1894 if (error == null) { 1895 assertTrue(list.get().size() > 0); 1896 return new Pair<>(list.get(), error); 1897 } else { 1898 assertFalse(list.get().size() > 0); 1899 return null; 1900 } 1901 } 1902 requestSelectedNbIotSatelliteSubscriptionId()1903 protected static Pair<Integer, Integer> requestSelectedNbIotSatelliteSubscriptionId() { 1904 final AtomicReference<Integer> selectedSatelliteSubscriptionId = 1905 new AtomicReference<>(); 1906 final AtomicReference<Integer> errorCode = new AtomicReference<>(); 1907 CountDownLatch latch = new CountDownLatch(1); 1908 OutcomeReceiver<Integer, SatelliteManager.SatelliteException> receiver = 1909 new OutcomeReceiver<>() { 1910 @Override 1911 public void onResult(Integer result) { 1912 logd("requestSelectedNbIotSatelliteSubscriptionId.onResult: result=" + 1913 result); 1914 selectedSatelliteSubscriptionId.set(result); 1915 latch.countDown(); 1916 } 1917 1918 @Override 1919 public void onError(SatelliteManager.SatelliteException exception) { 1920 logd("requestSelectedNbIotSatelliteSubscriptionId.onError: onError=" 1921 + exception.getErrorCode()); 1922 errorCode.set(exception.getErrorCode()); 1923 latch.countDown(); 1924 } 1925 }; 1926 1927 sSatelliteManager.requestSelectedNbIotSatelliteSubscriptionId( 1928 getContext().getMainExecutor(), receiver); 1929 try { 1930 assertTrue(latch.await(TIMEOUT, TimeUnit.MILLISECONDS)); 1931 } catch (InterruptedException e) { 1932 fail(e.toString()); 1933 } 1934 return new Pair<>(selectedSatelliteSubscriptionId.get(), errorCode.get()); 1935 } 1936 requestSatelliteDisplayName()1937 protected static Pair<CharSequence, Integer> requestSatelliteDisplayName() { 1938 final AtomicReference<CharSequence> displayNameForSubscription = new AtomicReference<>(); 1939 final AtomicReference<Integer> errorCode = new AtomicReference<>(); 1940 CountDownLatch latch = new CountDownLatch(1); 1941 OutcomeReceiver<CharSequence, SatelliteManager.SatelliteException> receiver = 1942 new OutcomeReceiver<>() { 1943 @Override 1944 public void onResult(CharSequence result) { 1945 logd("requestSatelliteDisplayName.onResult: result=" + 1946 result); 1947 displayNameForSubscription.set(result); 1948 latch.countDown(); 1949 } 1950 1951 @Override 1952 public void onError(SatelliteManager.SatelliteException exception) { 1953 logd("requestSatelliteDisplayName.onError: onError=" 1954 + exception); 1955 errorCode.set(exception.getErrorCode()); 1956 latch.countDown(); 1957 } 1958 }; 1959 1960 sSatelliteManager.requestSatelliteDisplayName( 1961 getContext().getMainExecutor(), receiver); 1962 try { 1963 assertTrue(latch.await(TIMEOUT, TimeUnit.MILLISECONDS)); 1964 } catch (InterruptedException e) { 1965 fail(e.toString()); 1966 } 1967 return new Pair<>(displayNameForSubscription.get(), errorCode.get()); 1968 } 1969 provisionSatellite(List<SatelliteSubscriberInfo> list)1970 protected static Pair<Boolean, Integer> provisionSatellite(List<SatelliteSubscriberInfo> list) { 1971 final AtomicReference<Boolean> requestResult = new AtomicReference<>(); 1972 final AtomicReference<Integer> errorCode = new AtomicReference<>(); 1973 CountDownLatch latch = new CountDownLatch(1); 1974 OutcomeReceiver<Void, SatelliteManager.SatelliteException> receiver = 1975 new OutcomeReceiver<>() { 1976 @Override 1977 public void onResult(Void result) { 1978 logd("provisionSatellite: onResult"); 1979 requestResult.set(true); 1980 latch.countDown(); 1981 } 1982 1983 @Override 1984 public void onError(SatelliteManager.SatelliteException exception) { 1985 logd("provisionSatellite: onError: onError=" + exception); 1986 errorCode.set(exception.getErrorCode()); 1987 latch.countDown(); 1988 } 1989 }; 1990 1991 sSatelliteManager.provisionSatellite(list, getContext().getMainExecutor(), receiver); 1992 try { 1993 assertTrue(latch.await(TIMEOUT, TimeUnit.MILLISECONDS)); 1994 } catch (InterruptedException e) { 1995 fail(e.toString()); 1996 } 1997 return new Pair<>(requestResult.get(), errorCode.get()); 1998 } 1999 deprovisionSatellite( List<SatelliteSubscriberInfo> list)2000 protected static Pair<Boolean, Integer> deprovisionSatellite( 2001 List<SatelliteSubscriberInfo> list) { 2002 final AtomicReference<Boolean> requestResult = new AtomicReference<>(); 2003 final AtomicReference<Integer> errorCode = new AtomicReference<>(); 2004 CountDownLatch latch = new CountDownLatch(1); 2005 OutcomeReceiver<Void, SatelliteManager.SatelliteException> receiver = 2006 new OutcomeReceiver<>() { 2007 @Override 2008 public void onResult(Void result) { 2009 logd("deprovisionSatellite: onResult"); 2010 requestResult.set(true); 2011 latch.countDown(); 2012 } 2013 2014 @Override 2015 public void onError(SatelliteManager.SatelliteException exception) { 2016 logd("deprovisionSatellite: onError: onError=" + exception); 2017 errorCode.set(exception.getErrorCode()); 2018 latch.countDown(); 2019 } 2020 }; 2021 2022 sSatelliteManager.deprovisionSatellite(list, getContext().getMainExecutor(), receiver); 2023 try { 2024 assertTrue(latch.await(TIMEOUT, TimeUnit.MILLISECONDS)); 2025 } catch (InterruptedException e) { 2026 fail(e.toString()); 2027 } 2028 return new Pair<>(requestResult.get(), errorCode.get()); 2029 } 2030 2031 @NonNull getConfigForSubId(Context context, int subId, String key)2032 protected static PersistableBundle getConfigForSubId(Context context, int subId, String key) { 2033 PersistableBundle config = null; 2034 CarrierConfigManager carrierConfigManager = context.getSystemService( 2035 CarrierConfigManager.class); 2036 if (carrierConfigManager != null) { 2037 config = carrierConfigManager.getConfigForSubId(subId, key); 2038 } 2039 if (config == null || config.isEmpty()) { 2040 config = CarrierConfigManager.getDefaultConfig(); 2041 } 2042 return config; 2043 } 2044 setDefaultSmsSubId(Context context, int subId)2045 protected void setDefaultSmsSubId(Context context, int subId) { 2046 SubscriptionManager subscriptionManager = context.getSystemService( 2047 SubscriptionManager.class); 2048 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(subscriptionManager, (sm) -> 2049 sm.setDefaultSmsSubId(subId), 2050 android.Manifest.permission.MODIFY_PHONE_STATE); 2051 } 2052 2053 protected static class SatelliteReceiverTest extends BroadcastReceiver { 2054 private final Semaphore mSemaphore = new Semaphore(0); 2055 2056 @Override onReceive(Context context, Intent intent)2057 public void onReceive(Context context, Intent intent) { 2058 if (SatelliteReceiver.TEST_INTENT.equals(intent.getAction())) { 2059 logd("SatelliteReceiverTest: receive the " 2060 + SatelliteManager.ACTION_SATELLITE_SUBSCRIBER_ID_LIST_CHANGED); 2061 mSemaphore.release(); 2062 } 2063 } 2064 clearQueue()2065 public void clearQueue() { 2066 logd("SatelliteReceiverTest: clearQueue"); 2067 mSemaphore.drainPermits(); 2068 } 2069 waitForReceive()2070 boolean waitForReceive() { 2071 try { 2072 if (!mSemaphore.tryAcquire(TimeUnit.SECONDS.toMillis(65), TimeUnit.MILLISECONDS)) { 2073 logd("SatelliteReceiverTest: Timeout to receive"); 2074 return false; 2075 } 2076 } catch (Exception ex) { 2077 logd("SatelliteReceiverTest: waitForReceive: Got exception=" + ex); 2078 return false; 2079 } 2080 return true; 2081 } 2082 } 2083 getExpectedSatelliteConfiguration()2084 protected List<SatelliteAccessConfiguration> getExpectedSatelliteConfiguration() { 2085 UUID uuid1 = UUID.fromString("0db0312f-d73f-444d-b99b-a893dfb42edf"); 2086 SatellitePosition satellitePosition1 = new SatellitePosition(-150.3, 35786000); 2087 List<Integer> bandList1 = new ArrayList<>(List.of(259, 260)); 2088 EarfcnRange earfcnRange1 = new EarfcnRange(3000, 4300); 2089 List<Integer> tagIdList1 = new ArrayList<>(List.of(6, 7, 8)); 2090 2091 SatelliteInfo satelliteInfo1 = new SatelliteInfo(uuid1, satellitePosition1, bandList1, 2092 new ArrayList<>(List.of(earfcnRange1))); 2093 2094 SatelliteAccessConfiguration configuration1 = new SatelliteAccessConfiguration( 2095 new ArrayList<>(List.of(satelliteInfo1)), tagIdList1); 2096 2097 UUID uuid2 = UUID.fromString("1dec24f8-9223-4196-ad7a-a03002db7af7"); 2098 SatellitePosition satellitePosition2 = new SatellitePosition(15.5, 35786000); 2099 List<Integer> bandList2 = new ArrayList<>(List.of(257, 258)); 2100 EarfcnRange earfcnRange2 = new EarfcnRange(3200, 3200); 2101 List<Integer> tagIdList2 = new ArrayList<>(List.of(9, 10, 11)); 2102 2103 SatelliteInfo satelliteInfo2 = new SatelliteInfo(uuid2, satellitePosition2, bandList2, 2104 new ArrayList<>(List.of(earfcnRange2))); 2105 2106 SatelliteAccessConfiguration configuration2 = new SatelliteAccessConfiguration( 2107 new ArrayList<>(List.of(satelliteInfo2)), tagIdList2); 2108 2109 UUID uuid3 = UUID.fromString("f60cb479-d85b-4f4e-b050-cc428f5eb4a4"); 2110 SatellitePosition satellitePosition3 = new SatellitePosition(-150, 35786000); 2111 List<Integer> bandList3 = new ArrayList<>(List.of(259, 260)); 2112 EarfcnRange earfcnRange3 = new EarfcnRange(3300, 3400); 2113 List<Integer> tagIdList3 = new ArrayList<>(List.of(12, 13, 14)); 2114 2115 SatelliteInfo satelliteInfo3 = new SatelliteInfo(uuid3, satellitePosition3, bandList3, 2116 new ArrayList<>(List.of(earfcnRange3))); 2117 2118 SatelliteAccessConfiguration configuration3 = new SatelliteAccessConfiguration( 2119 new ArrayList<>(List.of(satelliteInfo3)), tagIdList3); 2120 2121 UUID uuid4 = UUID.fromString("c5837d96-9585-46aa-8dd0-a974583737fb"); 2122 SatellitePosition satellitePosition4 = new SatellitePosition(-155, 35786000); 2123 List<Integer> bandList4 = new ArrayList<>(List.of(261, 262)); 2124 EarfcnRange earfcnRange4 = new EarfcnRange(3500, 3600); 2125 List<Integer> tagIdList4 = new ArrayList<>(List.of(15, 16, 17)); 2126 2127 SatelliteInfo satelliteInfo4 = new SatelliteInfo(uuid4, satellitePosition4, bandList4, 2128 new ArrayList<>(List.of(earfcnRange4))); 2129 2130 SatelliteAccessConfiguration configuration4 = new SatelliteAccessConfiguration( 2131 new ArrayList<>(List.of(satelliteInfo4)), tagIdList4); 2132 2133 UUID uuid5 = UUID.fromString("6ef2a128-0477-4271-895f-dc4a221d2b23"); 2134 SatellitePosition satellitePosition5 = new SatellitePosition(-66, 35786000); 2135 List<Integer> bandList5 = new ArrayList<>(List.of(263, 264)); 2136 EarfcnRange earfcnRange5 = new EarfcnRange(3700, 3800); 2137 List<Integer> tagIdList5 = new ArrayList<>(List.of(18, 19, 20)); 2138 2139 SatelliteInfo satelliteInfo5 = new SatelliteInfo(uuid5, satellitePosition5, bandList5, 2140 new ArrayList<>(List.of(earfcnRange5))); 2141 2142 SatelliteAccessConfiguration configuration5 = new SatelliteAccessConfiguration( 2143 new ArrayList<>(List.of(satelliteInfo5)), tagIdList5); 2144 2145 return new ArrayList<>( 2146 List.of(configuration1, configuration2, configuration3, configuration4, 2147 configuration5)); 2148 } 2149 verifySatelliteAccessConfiguration( @onNull SatelliteAccessConfiguration expectedConfiguration, @NonNull SystemSelectionSpecifier actualSystemSelectionSpecifier)2150 protected void verifySatelliteAccessConfiguration( 2151 @NonNull SatelliteAccessConfiguration expectedConfiguration, 2152 @NonNull SystemSelectionSpecifier actualSystemSelectionSpecifier) { 2153 2154 List<SatelliteInfo> expectedSatelliteInfos = 2155 expectedConfiguration.getSatelliteInfos(); 2156 List<Integer> expectedBandList = new ArrayList<>(); 2157 List<Integer> expectedEarfcnList = new ArrayList<>(); 2158 for (SatelliteInfo expectedSatelliteInfo : expectedSatelliteInfos) { 2159 expectedBandList.addAll(expectedSatelliteInfo.getBands()); 2160 List<EarfcnRange> earfcnRangeList = expectedSatelliteInfo.getEarfcnRanges(); 2161 earfcnRangeList.stream().flatMapToInt( 2162 earfcnRange -> IntStream.of(earfcnRange.getStartEarfcn(), 2163 earfcnRange.getEndEarfcn())).boxed().forEach(expectedEarfcnList::add); 2164 } 2165 2166 List<Integer> actualBandList = Arrays.stream(actualSystemSelectionSpecifier.getBands()) 2167 .boxed().collect(Collectors.toList()); 2168 2169 List<Integer> actualEarfcnList = Arrays.stream(actualSystemSelectionSpecifier.getEarfcns()) 2170 .boxed().collect(Collectors.toList()); 2171 2172 SatelliteInfo[] expectedSatelliteInfoArray = 2173 expectedConfiguration.getSatelliteInfos().toArray(new SatelliteInfo[0]); 2174 SatelliteInfo[] actualSatelliteInfoArray = 2175 actualSystemSelectionSpecifier.getSatelliteInfos().toArray(new SatelliteInfo[0]); 2176 2177 List<Integer> expectedTagIdList = expectedConfiguration.getTagIds(); 2178 List<Integer> actualTagIdList = Arrays.stream(actualSystemSelectionSpecifier.getTagIds()) 2179 .boxed().collect(Collectors.toList()); 2180 2181 assertEquals(expectedBandList, actualBandList); 2182 assertEquals(expectedEarfcnList, actualEarfcnList); 2183 assertArrayEquals(expectedSatelliteInfoArray, actualSatelliteInfoArray); 2184 assertEquals(expectedTagIdList, actualTagIdList); 2185 } 2186 2187 /** Get HAL version for the given HAL service. */ getHalVersion(int halService)2188 public int getHalVersion(int halService) { 2189 Pair<Integer, Integer> halVersion = sTelephonyManager.getHalVersion(halService); 2190 return makeRadioVersion(halVersion.first, halVersion.second); 2191 } 2192 makeRadioVersion(int major, int minor)2193 private static int makeRadioVersion(int major, int minor) { 2194 if (major < 0 || minor < 0) return 0; 2195 return major * 100 + minor; 2196 } 2197 } 2198