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 android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.Intent; 22 import android.os.Binder; 23 import android.os.IBinder; 24 import android.telephony.IBooleanConsumer; 25 import android.telephony.IIntegerConsumer; 26 import android.telephony.satellite.AntennaDirection; 27 import android.telephony.satellite.AntennaPosition; 28 import android.telephony.satellite.SatelliteManager; 29 import android.telephony.satellite.stub.INtnSignalStrengthConsumer; 30 import android.telephony.satellite.stub.ISatelliteCapabilitiesConsumer; 31 import android.telephony.satellite.stub.ISatelliteListener; 32 import android.telephony.satellite.stub.NTRadioTechnology; 33 import android.telephony.satellite.stub.NtnSignalStrength; 34 import android.telephony.satellite.stub.PointingInfo; 35 import android.telephony.satellite.stub.SatelliteCapabilities; 36 import android.telephony.satellite.stub.SatelliteDatagram; 37 import android.telephony.satellite.stub.SatelliteImplBase; 38 import android.telephony.satellite.stub.SatelliteModemEnableRequestAttributes; 39 import android.telephony.satellite.stub.SatelliteModemState; 40 import android.telephony.satellite.stub.SatelliteResult; 41 import android.telephony.satellite.stub.SatelliteService; 42 import android.telephony.satellite.stub.SystemSelectionSpecifier; 43 import android.util.Log; 44 45 import com.android.internal.util.FunctionalUtils; 46 47 import java.util.ArrayList; 48 import java.util.HashMap; 49 import java.util.LinkedList; 50 import java.util.List; 51 import java.util.Map; 52 import java.util.concurrent.Executor; 53 import java.util.concurrent.atomic.AtomicBoolean; 54 55 public class MockSatelliteService extends SatelliteImplBase { 56 public static final int NOT_UPDATED_SATELLITE_MODEM_STATE = -1; 57 private static final String TAG = "MockSatelliteService"; 58 59 // Hardcoded values below 60 private static final int SATELLITE_ALWAYS_VISIBLE = 0; 61 /** SatelliteCapabilities constant indicating that the radio technology is proprietary. */ 62 private static final int[] SUPPORTED_RADIO_TECHNOLOGIES = 63 new int[]{NTRadioTechnology.PROPRIETARY}; 64 /** SatelliteCapabilities constant indicating that pointing to satellite is required. */ 65 private static final boolean POINTING_TO_SATELLITE_REQUIRED = true; 66 /** SatelliteCapabilities constant indicating the maximum number of characters per datagram. */ 67 private static final int MAX_BYTES_PER_DATAGRAM = 339; 68 /** SatelliteCapabilities constant keys which are used to fill mAntennaPositionMap. */ 69 private static final int[] ANTENNA_POSITION_KEYS = new int[]{ 70 SatelliteManager.DISPLAY_MODE_OPENED, SatelliteManager.DISPLAY_MODE_CLOSED}; 71 /** SatelliteCapabilities constant values which are used to fill mAntennaPositionMap. */ 72 private static final AntennaPosition[] ANTENNA_POSITION_VALUES = new AntennaPosition[] { 73 new AntennaPosition(new AntennaDirection(1,1,1), 74 SatelliteManager.DEVICE_HOLD_POSITION_PORTRAIT), 75 new AntennaPosition(new AntennaDirection(2,2,2), 76 SatelliteManager.DEVICE_HOLD_POSITION_LANDSCAPE_LEFT) 77 }; 78 79 @NonNull 80 private final Map<IBinder, ISatelliteListener> mRemoteListeners = new HashMap<>(); 81 @Nullable private ILocalSatelliteListener mLocalListener; 82 private final LocalBinder mBinder = new LocalBinder(); 83 @SatelliteResult 84 private int mErrorCode = SatelliteResult.SATELLITE_RESULT_SUCCESS; 85 86 @SatelliteResult 87 private int mEnableCellularScanningErrorCode = SatelliteResult.SATELLITE_RESULT_SUCCESS; 88 // For local access of this Service. 89 class LocalBinder extends Binder { getService()90 MockSatelliteService getService() { 91 return MockSatelliteService.this; 92 } 93 } 94 95 private boolean mIsEnabled; 96 private boolean mIsSupported; 97 private int mModemState; 98 private final AtomicBoolean mWaitToSend = new AtomicBoolean(false); 99 private SatelliteDatagram mDatagramToBeSent; 100 private boolean mIsEmergencyDatagram; 101 private IIntegerConsumer mSendDatagramErrorCallback; 102 private Object mSendDatagramWithDelayLock = new Object(); 103 private static final long TIMEOUT = 1000; 104 private final AtomicBoolean mShouldRespondTelephony = new AtomicBoolean(true); 105 private final AtomicBoolean mShouldRespondEnableRequest = new AtomicBoolean(true); 106 private final AtomicBoolean mShouldNotifyRemoteServiceConnected = 107 new AtomicBoolean(false); 108 @Nullable private List<String> mCarrierPlmnList; 109 @Nullable private List<String> mAllSatellitePlmnList; 110 private boolean mIsSatelliteEnabledForCarrier; 111 private android.telephony.satellite.stub.NtnSignalStrength mNtnSignalStrength; 112 113 private int[] mSupportedRadioTechnologies; 114 private LinkedList<IIntegerConsumer> 115 mRequestSatelliteEnabledErrorCallbackQueue = new LinkedList<IIntegerConsumer>(); 116 private LinkedList<IIntegerConsumer> 117 mRequestSatelliteDisabledErrorCallbackQueue = new LinkedList<IIntegerConsumer>(); 118 private final Object mRequestSatelliteEnabledLock = new Object(); 119 private boolean mIsEmergnecy; 120 private List<SystemSelectionSpecifier> mSystemSelectionSpecifierList = new ArrayList<>(); 121 122 /** 123 * Create MockSatelliteService using the Executor specified for methods being called from 124 * the framework. 125 * 126 * @param executor The executor for the framework to use when executing satellite methods. 127 */ MockSatelliteService(@onNull Executor executor)128 public MockSatelliteService(@NonNull Executor executor) { 129 super(executor); 130 mIsEnabled = false; 131 mIsSupported = true; 132 mModemState = SatelliteModemState.SATELLITE_MODEM_STATE_OFF; 133 mSupportedRadioTechnologies = SUPPORTED_RADIO_TECHNOLOGIES; 134 mIsEmergnecy = false; 135 } 136 137 /** 138 * Zero-argument constructor to prevent service binding exception. 139 */ MockSatelliteService()140 public MockSatelliteService() { 141 this(Runnable::run); 142 } 143 144 @Override onBind(Intent intent)145 public IBinder onBind(Intent intent) { 146 if (SatelliteService.SERVICE_INTERFACE.equals(intent.getAction())) { 147 logd("Remote service bound"); 148 return getBinder(); 149 } 150 logd("Local service bound"); 151 return mBinder; 152 } 153 154 @Override onCreate()155 public void onCreate() { 156 super.onCreate(); 157 logd("onCreate"); 158 } 159 160 @Override onDestroy()161 public void onDestroy() { 162 super.onDestroy(); 163 logd("onDestroy"); 164 } 165 166 @Override setSatelliteListener(@onNull ISatelliteListener listener)167 public void setSatelliteListener(@NonNull ISatelliteListener listener) { 168 logd("setSatelliteListener"); 169 mRemoteListeners.put(listener.asBinder(), listener); 170 notifyRemoteServiceConnected(); 171 } 172 173 @Override requestSatelliteListeningEnabled(boolean enabled, int timeout, @NonNull IIntegerConsumer errorCallback)174 public void requestSatelliteListeningEnabled(boolean enabled, int timeout, 175 @NonNull IIntegerConsumer errorCallback) { 176 logd("requestSatelliteListeningEnabled: mErrorCode=" + mErrorCode); 177 178 if (mLocalListener != null) { 179 runWithExecutor(() -> mLocalListener.onSatelliteListeningEnabled(enabled)); 180 } else { 181 loge("requestSatelliteListeningEnabled: mLocalListener is null"); 182 } 183 184 if (!verifySatelliteModemState(errorCallback)) { 185 return; 186 } 187 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 188 if (mShouldRespondTelephony.get()) { 189 runWithExecutor(() -> errorCallback.accept(mErrorCode)); 190 } 191 return; 192 } 193 194 if (mShouldRespondTelephony.get()) { 195 runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS)); 196 } 197 if (enabled) { 198 updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_LISTENING); 199 } else { 200 updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_IDLE); 201 } 202 } 203 204 @Override requestSatelliteEnabled(SatelliteModemEnableRequestAttributes enableAttributes, @NonNull IIntegerConsumer errorCallback)205 public void requestSatelliteEnabled(SatelliteModemEnableRequestAttributes enableAttributes, 206 @NonNull IIntegerConsumer errorCallback) { 207 logd("requestSatelliteEnabled: mErrorCode=" + mErrorCode 208 + ", isEnabled=" + enableAttributes.isEnabled 209 + ", isDemoMode=" + enableAttributes.isDemoMode 210 + ", isEmergency= " + enableAttributes.isEmergencyMode 211 + ", iccId=" + enableAttributes.satelliteSubscriptionInfo.iccId 212 + ", niddApn=" + enableAttributes.satelliteSubscriptionInfo.niddApn 213 + ", mShouldRespondEnableRequest=" + mShouldRespondEnableRequest.get()); 214 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 215 if (mShouldRespondEnableRequest.get()) { 216 runWithExecutor(() -> errorCallback.accept(mErrorCode)); 217 } 218 return; 219 } 220 221 if (enableAttributes.isEnabled) { 222 enableSatellite(errorCallback); 223 } else { 224 disableSatellite(errorCallback); 225 } 226 mIsEmergnecy = enableAttributes.isEmergencyMode; 227 228 if (mLocalListener != null) { 229 runWithExecutor(() -> mLocalListener.onRequestSatelliteEnabled( 230 enableAttributes.isEmergencyMode)); 231 } else { 232 loge("requestSatelliteEnabled: mLocalListener is null"); 233 } 234 } 235 enableSatellite(@onNull IIntegerConsumer errorCallback)236 private void enableSatellite(@NonNull IIntegerConsumer errorCallback) { 237 if (mShouldRespondEnableRequest.get()) { 238 mIsEnabled = true; 239 runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS)); 240 updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_IDLE); 241 } else { 242 synchronized (mRequestSatelliteEnabledLock) { 243 mRequestSatelliteEnabledErrorCallbackQueue.addLast(errorCallback); 244 } 245 } 246 } 247 disableSatellite(@onNull IIntegerConsumer errorCallback)248 private void disableSatellite(@NonNull IIntegerConsumer errorCallback) { 249 if (mShouldRespondEnableRequest.get()) { 250 mIsEnabled = false; 251 runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS)); 252 updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_OFF); 253 } else { 254 synchronized (mRequestSatelliteEnabledLock) { 255 mRequestSatelliteDisabledErrorCallbackQueue.addLast(errorCallback); 256 } 257 } 258 } 259 260 @Override requestIsSatelliteEnabled(@onNull IIntegerConsumer errorCallback, @NonNull IBooleanConsumer callback)261 public void requestIsSatelliteEnabled(@NonNull IIntegerConsumer errorCallback, 262 @NonNull IBooleanConsumer callback) { 263 logd("requestIsSatelliteEnabled: mErrorCode=" + mErrorCode); 264 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 265 if (mShouldRespondTelephony.get()) { 266 runWithExecutor(() -> errorCallback.accept(mErrorCode)); 267 } 268 return; 269 } 270 if (mShouldRespondTelephony.get()) { 271 runWithExecutor(() -> callback.accept(mIsEnabled)); 272 } 273 } 274 275 @Override requestIsSatelliteSupported(@onNull IIntegerConsumer errorCallback, @NonNull IBooleanConsumer callback)276 public void requestIsSatelliteSupported(@NonNull IIntegerConsumer errorCallback, 277 @NonNull IBooleanConsumer callback) { 278 logd("requestIsSatelliteSupported"); 279 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 280 if (mShouldRespondTelephony.get()) { 281 runWithExecutor(() -> errorCallback.accept(mErrorCode)); 282 } 283 return; 284 } 285 if (mShouldRespondTelephony.get()) { 286 runWithExecutor(() -> callback.accept(mIsSupported)); 287 } 288 } 289 290 @Override requestSatelliteCapabilities(@onNull IIntegerConsumer errorCallback, @NonNull ISatelliteCapabilitiesConsumer callback)291 public void requestSatelliteCapabilities(@NonNull IIntegerConsumer errorCallback, 292 @NonNull ISatelliteCapabilitiesConsumer callback) { 293 logd("requestSatelliteCapabilities: mErrorCode=" + mErrorCode); 294 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 295 if (mShouldRespondTelephony.get()) { 296 runWithExecutor(() -> errorCallback.accept(mErrorCode)); 297 } 298 return; 299 } 300 301 if (mShouldRespondTelephony.get()) { 302 SatelliteCapabilities capabilities = new SatelliteCapabilities(); 303 capabilities.supportedRadioTechnologies = mSupportedRadioTechnologies; 304 capabilities.isPointingRequired = POINTING_TO_SATELLITE_REQUIRED; 305 capabilities.maxBytesPerOutgoingDatagram = MAX_BYTES_PER_DATAGRAM; 306 capabilities.antennaPositionKeys = ANTENNA_POSITION_KEYS; 307 capabilities.antennaPositionValues = ANTENNA_POSITION_VALUES; 308 runWithExecutor(() -> callback.accept(capabilities)); 309 } 310 } 311 312 @Override enableTerrestrialNetworkScanWhileSatelliteModeIsOn( boolean enabled, @NonNull IIntegerConsumer errorCallback)313 public void enableTerrestrialNetworkScanWhileSatelliteModeIsOn( 314 boolean enabled, @NonNull IIntegerConsumer errorCallback) { 315 logd("enableTerrestrialNetworkScanWhileSatelliteModeIsOn: enabled=" + enabled); 316 runWithExecutor(() -> errorCallback.accept(mEnableCellularScanningErrorCode)); 317 } 318 319 @Override startSendingSatellitePointingInfo(@onNull IIntegerConsumer errorCallback)320 public void startSendingSatellitePointingInfo(@NonNull IIntegerConsumer errorCallback) { 321 logd("startSendingSatellitePointingInfo: mErrorCode=" + mErrorCode); 322 if (!verifySatelliteModemState(errorCallback)) { 323 if (mLocalListener != null) { 324 runWithExecutor(() -> mLocalListener.onStartSendingSatellitePointingInfo()); 325 } else { 326 loge("startSendingSatellitePointingInfo: mLocalListener is null"); 327 } 328 return; 329 } 330 331 if (mShouldRespondTelephony.get()) { 332 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 333 runWithExecutor(() -> errorCallback.accept(mErrorCode)); 334 } else { 335 runWithExecutor(() -> errorCallback.accept( 336 SatelliteResult.SATELLITE_RESULT_SUCCESS)); 337 } 338 } 339 340 if (mLocalListener != null) { 341 runWithExecutor(() -> mLocalListener.onStartSendingSatellitePointingInfo()); 342 } else { 343 loge("startSendingSatellitePointingInfo: mLocalListener is null"); 344 } 345 } 346 347 @Override stopSendingSatellitePointingInfo(@onNull IIntegerConsumer errorCallback)348 public void stopSendingSatellitePointingInfo(@NonNull IIntegerConsumer errorCallback) { 349 logd("stopSendingSatellitePointingInfo: mErrorCode=" + mErrorCode); 350 if (mShouldRespondTelephony.get()) { 351 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 352 runWithExecutor(() -> errorCallback.accept(mErrorCode)); 353 } else { 354 runWithExecutor(() -> errorCallback.accept( 355 SatelliteResult.SATELLITE_RESULT_SUCCESS)); 356 } 357 } 358 359 if (mLocalListener != null) { 360 runWithExecutor(() -> mLocalListener.onStopSendingSatellitePointingInfo()); 361 } else { 362 loge("stopSendingSatellitePointingInfo: mLocalListener is null"); 363 } 364 } 365 366 @Override pollPendingSatelliteDatagrams(@onNull IIntegerConsumer errorCallback)367 public void pollPendingSatelliteDatagrams(@NonNull IIntegerConsumer errorCallback) { 368 logd("pollPendingSatelliteDatagrams: mErrorCode=" + mErrorCode); 369 updateSatelliteModemState( 370 SatelliteModemState.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING); 371 if (mShouldRespondTelephony.get()) { 372 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 373 runWithExecutor(() -> errorCallback.accept(mErrorCode)); 374 } else { 375 runWithExecutor(() -> errorCallback.accept( 376 SatelliteResult.SATELLITE_RESULT_SUCCESS)); 377 } 378 } 379 380 if (mLocalListener != null) { 381 runWithExecutor(() -> mLocalListener.onPollPendingSatelliteDatagrams()); 382 } else { 383 loge("pollPendingSatelliteDatagrams: mLocalListener is null"); 384 } 385 } 386 387 @Override sendSatelliteDatagram(@onNull SatelliteDatagram datagram, boolean isEmergency, @NonNull IIntegerConsumer errorCallback)388 public void sendSatelliteDatagram(@NonNull SatelliteDatagram datagram, boolean isEmergency, 389 @NonNull IIntegerConsumer errorCallback) { 390 logd("sendDatagram: mErrorCode=" + mErrorCode); 391 392 if (mWaitToSend.get()) { 393 synchronized (mSendDatagramWithDelayLock) { 394 // Save the datagram 395 mDatagramToBeSent = datagram; 396 mIsEmergencyDatagram = isEmergency; 397 mSendDatagramErrorCallback = errorCallback; 398 } 399 400 if (mLocalListener != null) { 401 runWithExecutor(() -> mLocalListener.onSendSatelliteDatagram( 402 datagram, isEmergency)); 403 } else { 404 loge("sendDatagram: mLocalListener is null"); 405 } 406 } else { 407 updateSatelliteModemState( 408 SatelliteModemState.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING); 409 if (mShouldRespondTelephony.get()) { 410 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 411 runWithExecutor(() -> errorCallback.accept(mErrorCode)); 412 } else { 413 runWithExecutor(() -> errorCallback.accept( 414 SatelliteResult.SATELLITE_RESULT_SUCCESS)); 415 } 416 } 417 418 if (mLocalListener != null) { 419 runWithExecutor(() -> mLocalListener.onSendSatelliteDatagram( 420 datagram, isEmergency)); 421 } else { 422 loge("sendDatagram: mLocalListener is null"); 423 } 424 updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_IDLE); 425 } 426 } 427 428 @Override requestSatelliteModemState(@onNull IIntegerConsumer errorCallback, @NonNull IIntegerConsumer callback)429 public void requestSatelliteModemState(@NonNull IIntegerConsumer errorCallback, 430 @NonNull IIntegerConsumer callback) { 431 logd("requestSatelliteModemState: mErrorCode=" + mErrorCode); 432 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 433 if (mShouldRespondTelephony.get()) { 434 runWithExecutor(() -> errorCallback.accept(mErrorCode)); 435 } 436 return; 437 } 438 if (mShouldRespondTelephony.get()) { 439 runWithExecutor(() -> callback.accept(mModemState)); 440 } 441 } 442 443 @Override requestTimeForNextSatelliteVisibility(@onNull IIntegerConsumer errorCallback, @NonNull IIntegerConsumer callback)444 public void requestTimeForNextSatelliteVisibility(@NonNull IIntegerConsumer errorCallback, 445 @NonNull IIntegerConsumer callback) { 446 logd("requestTimeForNextSatelliteVisibility: mErrorCode=" + mErrorCode); 447 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 448 if (mShouldRespondTelephony.get()) { 449 runWithExecutor(() -> errorCallback.accept(mErrorCode)); 450 } 451 return; 452 } 453 if (mShouldRespondTelephony.get()) { 454 runWithExecutor(() -> callback.accept(SATELLITE_ALWAYS_VISIBLE)); 455 } 456 } 457 458 @Override setSatellitePlmn(@onNull int simLogicalSlotIndex, @NonNull List<String> carrierPlmnList, @NonNull List<String> allSatellitePlmnList, @NonNull IIntegerConsumer errorCallback)459 public void setSatellitePlmn(@NonNull int simLogicalSlotIndex, 460 @NonNull List<String> carrierPlmnList, 461 @NonNull List<String> allSatellitePlmnList, 462 @NonNull IIntegerConsumer errorCallback) { 463 logd("setSatellitePlmn: mErrorCode=" + mErrorCode); 464 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 465 if (mShouldRespondTelephony.get()) { 466 runWithExecutor(() -> errorCallback.accept(mErrorCode)); 467 } 468 return; 469 } 470 if (mShouldRespondTelephony.get()) { 471 runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS)); 472 } 473 474 mCarrierPlmnList = carrierPlmnList; 475 mAllSatellitePlmnList = allSatellitePlmnList; 476 477 if (mLocalListener != null) { 478 runWithExecutor(() -> mLocalListener.onSetSatellitePlmn()); 479 } else { 480 loge("setSatellitePlmn: mLocalListener is null"); 481 } 482 } 483 484 @Override setSatelliteEnabledForCarrier(@onNull int simLogicalSlotIndex, @NonNull boolean satelliteEnabled, @NonNull IIntegerConsumer callback)485 public void setSatelliteEnabledForCarrier(@NonNull int simLogicalSlotIndex, 486 @NonNull boolean satelliteEnabled, 487 @NonNull IIntegerConsumer callback) { 488 logd("setSatelliteEnabledForCarrier: mErrorCode=" + mErrorCode 489 + ", satelliteEnabled=" + satelliteEnabled 490 + ", mShouldRespondTelephony=" + mShouldRespondTelephony.get()); 491 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 492 if (mShouldRespondTelephony.get()) { 493 runWithExecutor(() -> callback.accept(mErrorCode)); 494 } 495 return; 496 } 497 498 mIsSatelliteEnabledForCarrier = satelliteEnabled; 499 if (mShouldRespondTelephony.get()) { 500 runWithExecutor(() -> callback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS)); 501 } 502 } 503 504 @Override requestIsSatelliteEnabledForCarrier(@onNull int simLogicalSlotIndex, @NonNull IIntegerConsumer resultCallback, @NonNull IBooleanConsumer callback)505 public void requestIsSatelliteEnabledForCarrier(@NonNull int simLogicalSlotIndex, 506 @NonNull IIntegerConsumer resultCallback, @NonNull IBooleanConsumer callback) { 507 logd("requestIsSatelliteEnabledForCarrier: mErrorCode=" + mErrorCode); 508 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 509 if (mShouldRespondTelephony.get()) { 510 runWithExecutor(() -> resultCallback.accept(mErrorCode)); 511 } 512 return; 513 } 514 if (mShouldRespondTelephony.get()) { 515 runWithExecutor(() -> callback.accept(mIsSatelliteEnabledForCarrier)); 516 } 517 } 518 519 @Override requestSignalStrength(@onNull IIntegerConsumer resultCallback, INtnSignalStrengthConsumer callback)520 public void requestSignalStrength(@NonNull IIntegerConsumer resultCallback, 521 INtnSignalStrengthConsumer callback) { 522 logd("requestSignalStrength: mErrorCode=" + mErrorCode); 523 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 524 if (mShouldRespondTelephony.get()) { 525 runWithExecutor(() -> resultCallback.accept(mErrorCode)); 526 } 527 return; 528 } 529 if (mShouldRespondTelephony.get()) { 530 runWithExecutor(() -> callback.accept(mNtnSignalStrength)); 531 } 532 } 533 534 @Override startSendingNtnSignalStrength(@onNull IIntegerConsumer resultCallback)535 public void startSendingNtnSignalStrength(@NonNull IIntegerConsumer resultCallback) { 536 logd("startSendingNtnSignalStrength: mErrorCode=" + mErrorCode); 537 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 538 if (mShouldRespondTelephony.get()) { 539 runWithExecutor(() -> resultCallback.accept(mErrorCode)); 540 } 541 } 542 } 543 544 @Override stopSendingNtnSignalStrength(@onNull IIntegerConsumer resultCallback)545 public void stopSendingNtnSignalStrength(@NonNull IIntegerConsumer resultCallback) { 546 logd("stopSendingNtnSignalStrength: mErrorCode=" + mErrorCode); 547 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 548 if (mShouldRespondTelephony.get()) { 549 runWithExecutor(() -> resultCallback.accept(mErrorCode)); 550 } 551 } 552 } 553 554 @Override updateSatelliteSubscription(@onNull String iccId, @NonNull IIntegerConsumer resultCallback)555 public void updateSatelliteSubscription(@NonNull String iccId, 556 @NonNull IIntegerConsumer resultCallback) { 557 logd("updateSatelliteSubscription: iccId=" + iccId + " mErrorCode=" + mErrorCode); 558 559 if (mShouldRespondTelephony.get()) { 560 runWithExecutor(() -> resultCallback.accept(mErrorCode)); 561 } 562 } 563 564 @Override updateSystemSelectionChannels( @onNull List<SystemSelectionSpecifier> systemSelectionSpecifiers, @NonNull IIntegerConsumer resultCallback)565 public void updateSystemSelectionChannels( 566 @NonNull List<SystemSelectionSpecifier> systemSelectionSpecifiers, 567 @NonNull IIntegerConsumer resultCallback) { 568 logd("updateSystemSelectionChannels: mErrorCode=" + mErrorCode 569 + ", mShouldRespondTelephony=" + mShouldRespondTelephony.get()); 570 571 if (mErrorCode == SatelliteResult.SATELLITE_RESULT_SUCCESS) { 572 mSystemSelectionSpecifierList = new ArrayList<>(systemSelectionSpecifiers); 573 } 574 575 if (mShouldRespondTelephony.get()) { 576 runWithExecutor(() -> resultCallback.accept(mErrorCode)); 577 } 578 } 579 580 581 /** 582 * Returns the configured list of SystemSelectionSpecifiers. 583 * 584 * @return the list of configured system selection specifier. 585 */ getSystemSelectionChannels()586 public List<SystemSelectionSpecifier> getSystemSelectionChannels() { 587 logd("getSystemSelectionChannels: mSystemSelectionSpecifierList=" 588 + mSystemSelectionSpecifierList); 589 return mSystemSelectionSpecifierList; 590 } 591 setLocalSatelliteListener(@onNull ILocalSatelliteListener listener)592 public void setLocalSatelliteListener(@NonNull ILocalSatelliteListener listener) { 593 logd("setLocalSatelliteListener: listener=" + listener); 594 mLocalListener = listener; 595 if (mShouldNotifyRemoteServiceConnected.get()) { 596 notifyRemoteServiceConnected(); 597 } 598 } 599 setErrorCode(@atelliteResult int errorCode)600 public void setErrorCode(@SatelliteResult int errorCode) { 601 logd("setErrorCode: errorCode=" + errorCode); 602 mErrorCode = errorCode; 603 } 604 605 /** 606 * This API is used by CTS test cases to update current NTN signal strength of the mock 607 * satellite modem. 608 */ setNtnSignalStrength( android.telephony.satellite.stub.NtnSignalStrength ntnSignalStrength)609 public void setNtnSignalStrength( 610 android.telephony.satellite.stub.NtnSignalStrength ntnSignalStrength) { 611 logd("setNtnSignalStrength: ntnSignalStrengthLevel=" 612 + ntnSignalStrength.signalStrengthLevel); 613 mNtnSignalStrength = ntnSignalStrength; 614 } 615 616 /** 617 * This API is used by CTS test cases to set the error code returned when the mock satellite 618 * modem receives requests to enable or disable cellular scanning mode. 619 */ setEnableCellularScanningErrorCode(@atelliteResult int errorCode)620 public void setEnableCellularScanningErrorCode(@SatelliteResult int errorCode) { 621 logd("setEnableCellularScanningErrorCode: errorCode=" + errorCode); 622 mEnableCellularScanningErrorCode = errorCode; 623 } 624 625 /** 626 * This API is used by CTS test cases to update supported NTN radio technologies of the 627 * mock satellite modem. 628 */ setSupportedRadioTechnologies(@onNull int[] supportedRadioTechnologies)629 public void setSupportedRadioTechnologies(@NonNull int[] supportedRadioTechnologies) { 630 logd("setSupportedRadioTechnologies: supportedRadioTechnologies=" 631 + supportedRadioTechnologies[0]); 632 mSupportedRadioTechnologies = supportedRadioTechnologies; 633 } 634 setSatelliteSupport(boolean supported)635 public void setSatelliteSupport(boolean supported) { 636 logd("setSatelliteSupport: supported=" + supported); 637 mIsSupported = supported; 638 } 639 setShouldRespondTelephony(boolean shouldRespondTelephony)640 public void setShouldRespondTelephony(boolean shouldRespondTelephony) { 641 mShouldRespondTelephony.set(shouldRespondTelephony); 642 logd("setShouldRespondTelephony: shouldRespondTelephony=" + shouldRespondTelephony); 643 } 644 setShouldRespondEnableRequest(boolean shouldRespond)645 public void setShouldRespondEnableRequest(boolean shouldRespond) { 646 mShouldRespondEnableRequest.set(shouldRespond); 647 logd("setShouldRespondEnableRequest: shouldRespond=" + shouldRespond); 648 } 649 sendOnSatelliteDatagramReceived(SatelliteDatagram datagram, int pendingCount)650 public void sendOnSatelliteDatagramReceived(SatelliteDatagram datagram, int pendingCount) { 651 logd("sendOnSatelliteDatagramReceived"); 652 mRemoteListeners.values().forEach(listener -> runWithExecutor(() -> 653 listener.onSatelliteDatagramReceived(datagram, pendingCount))); 654 updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_IDLE); 655 } 656 sendOnPendingDatagrams()657 public void sendOnPendingDatagrams() { 658 logd("sendOnPendingDatagrams"); 659 mRemoteListeners.values().forEach(listener -> runWithExecutor(() -> 660 listener.onPendingDatagrams())); 661 } 662 sendOnSatellitePositionChanged(PointingInfo pointingInfo)663 public void sendOnSatellitePositionChanged(PointingInfo pointingInfo) { 664 logd("sendOnSatellitePositionChanged"); 665 mRemoteListeners.values().forEach(listener -> runWithExecutor(() -> 666 listener.onSatellitePositionChanged(pointingInfo))); 667 } 668 669 /** 670 * This API is used by CTS test cases to update satellite modem state. 671 */ sendOnSatelliteModemStateChanged(int modemState)672 public void sendOnSatelliteModemStateChanged(int modemState) { 673 updateSatelliteModemState(modemState); 674 } 675 676 /** 677 * Called when NTN signal strength changes. 678 * This API is used by CTS test cases to update NTN signal strength. 679 * @param ntnSignalStrength The new NTN signal strength. 680 */ sendOnNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength)681 public void sendOnNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) { 682 logd("sendOnNtnSignalStrengthChanged"); 683 mNtnSignalStrength = ntnSignalStrength; 684 mRemoteListeners.values().forEach(listener -> runWithExecutor(() -> 685 listener.onNtnSignalStrengthChanged(ntnSignalStrength))); 686 } 687 688 /** 689 * Called when satellite capabilities has changed. 690 * This API is used by CTS test cases to update satellite capabilities. 691 * @param satelliteCapabilities The new satellite capabilities. 692 */ sendOnSatelliteCapabilitiesChanged(SatelliteCapabilities satelliteCapabilities)693 public void sendOnSatelliteCapabilitiesChanged(SatelliteCapabilities satelliteCapabilities) { 694 logd("sendOnSatelliteCapabilitiesChanged"); 695 mRemoteListeners.values().forEach(listener -> runWithExecutor(() -> 696 listener.onSatelliteCapabilitiesChanged(satelliteCapabilities))); 697 } 698 699 /** 700 * This API is used by CTS test cases to update satellite supported state. 701 * @param supported The new satellite supported state. 702 */ sendOnSatelliteSupportedStateChanged(boolean supported)703 public void sendOnSatelliteSupportedStateChanged(boolean supported) { 704 logd("sendOnSatelliteSupportedStateChanged: supported=" + supported); 705 mRemoteListeners.values().forEach(listener -> runWithExecutor(() -> 706 listener.onSatelliteSupportedStateChanged(supported))); 707 } 708 setWaitToSend(boolean wait)709 public void setWaitToSend(boolean wait) { 710 mWaitToSend.set(wait); 711 } 712 sendSavedDatagram()713 public boolean sendSavedDatagram() { 714 synchronized (mSendDatagramWithDelayLock) { 715 logd("sendSavedDatagram"); 716 if (mSendDatagramErrorCallback == null) { 717 return false; 718 } 719 720 if (mShouldRespondTelephony.get()) { 721 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) { 722 runWithExecutor(() -> mSendDatagramErrorCallback.accept(mErrorCode)); 723 } else { 724 runWithExecutor(() -> mSendDatagramErrorCallback.accept( 725 SatelliteResult.SATELLITE_RESULT_SUCCESS)); 726 } 727 } 728 mSendDatagramErrorCallback = null; 729 return true; 730 } 731 } 732 733 /** 734 * Respond to the oldest enable/disable request. 735 */ respondToRequestSatelliteEnabled(boolean isEnabled, int modemState)736 public boolean respondToRequestSatelliteEnabled(boolean isEnabled, int modemState) { 737 synchronized (mRequestSatelliteEnabledLock) { 738 if (isEnabled) { 739 logd("respondToRequestSatelliteEnabled: isEnabled=true, " 740 + "mRequestSatelliteEnabledErrorCallbackQueue=" 741 + mRequestSatelliteEnabledErrorCallbackQueue.size()); 742 if (mRequestSatelliteEnabledErrorCallbackQueue.isEmpty()) { 743 return false; 744 } 745 runWithExecutor(() -> mRequestSatelliteEnabledErrorCallbackQueue 746 .removeFirst().accept(mErrorCode)); 747 } else { 748 logd("respondToRequestSatelliteEnabled: isEnabled=false, " 749 + "mRequestSatelliteDisabledErrorCallbackQueue=" 750 + mRequestSatelliteDisabledErrorCallbackQueue.size()); 751 if (mRequestSatelliteDisabledErrorCallbackQueue.isEmpty()) { 752 return false; 753 } 754 runWithExecutor(() -> mRequestSatelliteDisabledErrorCallbackQueue 755 .removeFirst().accept(mErrorCode)); 756 } 757 if (modemState != NOT_UPDATED_SATELLITE_MODEM_STATE) { 758 updateSatelliteModemState(modemState); 759 } 760 return true; 761 } 762 } 763 764 /** 765 * Clear the enable request queues. 766 */ clearSatelliteEnableRequestQueues()767 public void clearSatelliteEnableRequestQueues() { 768 synchronized (mRequestSatelliteEnabledLock) { 769 logd("clearSatelliteEnableRequestQueues: isEnabled=true, " 770 + "mRequestSatelliteEnabledErrorCallbackQueue=" 771 + mRequestSatelliteEnabledErrorCallbackQueue.size() 772 + "mRequestSatelliteDisabledErrorCallbackQueue=" 773 + mRequestSatelliteDisabledErrorCallbackQueue.size()); 774 mRequestSatelliteEnabledErrorCallbackQueue.clear(); 775 mRequestSatelliteDisabledErrorCallbackQueue.clear(); 776 } 777 } 778 779 780 /** 781 * Get the configured PLMN list supported by carrier. 782 */ getCarrierPlmnList()783 public List<String> getCarrierPlmnList() { 784 logd("getCarrierPlmnList"); 785 return mCarrierPlmnList; 786 } 787 788 /** 789 * Get the configured all satellite PLMN list. 790 */ getAllSatellitePlmnList()791 public List<String> getAllSatellitePlmnList() { 792 logd("getAllSatellitePlmnList"); 793 return mAllSatellitePlmnList; 794 } 795 getIsSatelliteEnabledForCarrier()796 public boolean getIsSatelliteEnabledForCarrier() { 797 logd("getIsSatelliteEnabledForCarrier"); 798 return mIsSatelliteEnabledForCarrier; 799 } 800 clearSatelliteEnabledForCarrier()801 public void clearSatelliteEnabledForCarrier() { 802 mIsSatelliteEnabledForCarrier = false; 803 } 804 805 /** 806 * Helper method to verify that the satellite modem is properly configured to receive 807 * requests. 808 * 809 * @param errorCallback The callback to notify of any errors preventing satellite requests. 810 * @return {@code true} if the satellite modem is configured to receive requests and 811 * {@code false} if it is not. 812 */ verifySatelliteModemState(@onNull IIntegerConsumer errorCallback)813 private boolean verifySatelliteModemState(@NonNull IIntegerConsumer errorCallback) { 814 if (!mIsSupported) { 815 runWithExecutor(() -> errorCallback.accept( 816 SatelliteResult.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED)); 817 return false; 818 } 819 if (!mIsEnabled) { 820 runWithExecutor(() -> errorCallback.accept( 821 SatelliteResult.SATELLITE_RESULT_INVALID_MODEM_STATE)); 822 return false; 823 } 824 return true; 825 } 826 827 /** 828 * Update the satellite modem state and notify listeners if it changed. 829 * 830 * @param modemState The {@link SatelliteModemState} to update. 831 */ updateSatelliteModemState(int modemState)832 private void updateSatelliteModemState(int modemState) { 833 logd("updateSatelliteModemState modemState=" + modemState); 834 mRemoteListeners.values().forEach(listener -> runWithExecutor(() -> 835 listener.onSatelliteModemStateChanged(modemState))); 836 mModemState = modemState; 837 } 838 839 /** 840 * Get the emergency mode or not 841 */ getIsEmergency()842 public boolean getIsEmergency() { 843 logd("getIsEmergency: mIsEmergnecy=" + mIsEmergnecy); 844 return mIsEmergnecy; 845 } 846 847 /** 848 * Execute the given runnable using the executor that this service was created with. 849 * 850 * @param r A runnable that can throw an exception. 851 */ runWithExecutor(@onNull FunctionalUtils.ThrowingRunnable r)852 private void runWithExecutor(@NonNull FunctionalUtils.ThrowingRunnable r) { 853 mExecutor.execute(() -> Binder.withCleanCallingIdentity(r)); 854 } 855 notifyRemoteServiceConnected()856 private void notifyRemoteServiceConnected() { 857 logd("notifyRemoteServiceConnected"); 858 if (mLocalListener != null) { 859 runWithExecutor(() -> mLocalListener.onRemoteServiceConnected()); 860 mShouldNotifyRemoteServiceConnected.set(false); 861 } else { 862 mShouldNotifyRemoteServiceConnected.set(true); 863 } 864 } 865 866 /** 867 * Log the message to the radio buffer with {@code DEBUG} priority. 868 * 869 * @param log The message to log. 870 */ logd(@onNull String log)871 private static void logd(@NonNull String log) { 872 Log.d(TAG, log); 873 } 874 875 /** 876 * Log with error attribute 877 * 878 * @param s is string log 879 */ loge(@onNull String s)880 protected void loge(@NonNull String s) { 881 Log.e(TAG, s); 882 } 883 } 884