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 com.android.internal.telephony.satellite; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.ServiceConnection; 25 import android.os.AsyncResult; 26 import android.os.Binder; 27 import android.os.Handler; 28 import android.os.IBinder; 29 import android.os.Looper; 30 import android.os.Message; 31 import android.os.RegistrantList; 32 import android.os.RemoteException; 33 import android.telephony.DropBoxManagerLoggerBackend; 34 import android.telephony.IBooleanConsumer; 35 import android.telephony.IIntegerConsumer; 36 import android.telephony.PersistentLogger; 37 import android.telephony.Rlog; 38 import android.telephony.satellite.NtnSignalStrength; 39 import android.telephony.satellite.SatelliteCapabilities; 40 import android.telephony.satellite.SatelliteDatagram; 41 import android.telephony.satellite.SatelliteManager; 42 import android.telephony.satellite.SatelliteManager.SatelliteException; 43 import android.telephony.satellite.stub.INtnSignalStrengthConsumer; 44 import android.telephony.satellite.stub.ISatellite; 45 import android.telephony.satellite.stub.ISatelliteCapabilitiesConsumer; 46 import android.telephony.satellite.stub.ISatelliteListener; 47 import android.telephony.satellite.stub.SatelliteModemState; 48 import android.telephony.satellite.stub.SatelliteService; 49 import android.text.TextUtils; 50 import android.util.Pair; 51 52 import com.android.internal.R; 53 import com.android.internal.annotations.VisibleForTesting; 54 import com.android.internal.telephony.ExponentialBackoff; 55 import com.android.internal.telephony.flags.FeatureFlags; 56 57 import java.util.Arrays; 58 import java.util.List; 59 60 /** 61 * Satellite modem interface to manage connections with the satellite service and HAL interface. 62 */ 63 public class SatelliteModemInterface { 64 private static final String TAG = "SatelliteModemInterface"; 65 private static final long REBIND_INITIAL_DELAY = 2 * 1000; // 2 seconds 66 private static final long REBIND_MAXIMUM_DELAY = 64 * 1000; // 1 minute 67 private static final int REBIND_MULTIPLIER = 2; 68 69 @NonNull private static SatelliteModemInterface sInstance; 70 @NonNull private final Context mContext; 71 @NonNull private final DemoSimulator mDemoSimulator; 72 @NonNull private final SatelliteListener mVendorListener; 73 @NonNull private final SatelliteListener mDemoListener; 74 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 75 @NonNull protected final ExponentialBackoff mExponentialBackoff; 76 @NonNull private final Object mLock = new Object(); 77 @NonNull private final SatelliteController mSatelliteController; 78 /** 79 * {@code true} to use the vendor satellite service and {@code false} to use the HAL. 80 */ 81 private boolean mIsSatelliteServiceSupported; 82 @Nullable private ISatellite mSatelliteService; 83 @Nullable private SatelliteServiceConnection mSatelliteServiceConnection; 84 @NonNull private String mVendorSatellitePackageName = ""; 85 private boolean mIsBound; 86 private boolean mIsBinding; 87 @Nullable private PersistentLogger mPersistentLogger = null; 88 89 @NonNull private final RegistrantList mSatelliteProvisionStateChangedRegistrants = 90 new RegistrantList(); 91 @NonNull private final RegistrantList mSatellitePositionInfoChangedRegistrants = 92 new RegistrantList(); 93 @NonNull private final RegistrantList mDatagramTransferStateChangedRegistrants = 94 new RegistrantList(); 95 @NonNull private final RegistrantList mSatelliteModemStateChangedRegistrants = 96 new RegistrantList(); 97 @NonNull private final RegistrantList mPendingDatagramsRegistrants = new RegistrantList(); 98 @NonNull private final RegistrantList mSatelliteDatagramsReceivedRegistrants = 99 new RegistrantList(); 100 @NonNull private final RegistrantList mNtnSignalStrengthChangedRegistrants = 101 new RegistrantList(); 102 @NonNull private final RegistrantList mSatelliteCapabilitiesChangedRegistrants = 103 new RegistrantList(); 104 @NonNull private final RegistrantList mSatelliteSupportedStateChangedRegistrants = 105 new RegistrantList(); 106 107 private class SatelliteListener extends ISatelliteListener.Stub { 108 109 private final boolean mIsDemoListener; 110 SatelliteListener(boolean isDemoListener)111 SatelliteListener(boolean isDemoListener) { 112 mIsDemoListener = isDemoListener; 113 } 114 115 @Override onSatelliteProvisionStateChanged(boolean provisioned)116 public void onSatelliteProvisionStateChanged(boolean provisioned) { 117 mSatelliteProvisionStateChangedRegistrants.notifyResult(provisioned); 118 } 119 120 @Override onSatelliteDatagramReceived( android.telephony.satellite.stub.SatelliteDatagram datagram, int pendingCount)121 public void onSatelliteDatagramReceived( 122 android.telephony.satellite.stub.SatelliteDatagram datagram, int pendingCount) { 123 if (notifyResultIfExpectedListener()) { 124 plogd("onSatelliteDatagramReceived: pendingCount=" + pendingCount); 125 mSatelliteDatagramsReceivedRegistrants.notifyResult(new Pair<>( 126 SatelliteServiceUtils.fromSatelliteDatagram(datagram), pendingCount)); 127 } 128 } 129 130 @Override onPendingDatagrams()131 public void onPendingDatagrams() { 132 if (notifyResultIfExpectedListener()) { 133 plogd("onPendingDatagrams"); 134 mPendingDatagramsRegistrants.notifyResult(null); 135 } 136 } 137 138 @Override onSatellitePositionChanged( android.telephony.satellite.stub.PointingInfo pointingInfo)139 public void onSatellitePositionChanged( 140 android.telephony.satellite.stub.PointingInfo pointingInfo) { 141 mSatellitePositionInfoChangedRegistrants.notifyResult( 142 SatelliteServiceUtils.fromPointingInfo(pointingInfo)); 143 } 144 145 @Override onSatelliteModemStateChanged(int state)146 public void onSatelliteModemStateChanged(int state) { 147 if (notifyModemStateChanged(state)) { 148 mSatelliteModemStateChangedRegistrants.notifyResult( 149 SatelliteServiceUtils.fromSatelliteModemState(state)); 150 int datagramTransferState = 151 SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN; 152 switch (state) { 153 case SatelliteManager.SATELLITE_MODEM_STATE_IDLE: 154 datagramTransferState = 155 SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE; 156 break; 157 case SatelliteManager.SATELLITE_MODEM_STATE_LISTENING: 158 datagramTransferState = 159 SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING; 160 break; 161 case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING: 162 datagramTransferState = 163 SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING; 164 break; 165 case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING: 166 // keep previous state as this could be retrying sending or receiving 167 break; 168 } 169 mDatagramTransferStateChangedRegistrants.notifyResult(datagramTransferState); 170 } 171 } 172 173 @Override onNtnSignalStrengthChanged( android.telephony.satellite.stub.NtnSignalStrength ntnSignalStrength)174 public void onNtnSignalStrengthChanged( 175 android.telephony.satellite.stub.NtnSignalStrength ntnSignalStrength) { 176 if (notifyResultIfExpectedListener()) { 177 mNtnSignalStrengthChangedRegistrants.notifyResult( 178 SatelliteServiceUtils.fromNtnSignalStrength(ntnSignalStrength)); 179 } 180 } 181 182 @Override onSatelliteCapabilitiesChanged( android.telephony.satellite.stub.SatelliteCapabilities satelliteCapabilities)183 public void onSatelliteCapabilitiesChanged( 184 android.telephony.satellite.stub.SatelliteCapabilities satelliteCapabilities) { 185 mSatelliteCapabilitiesChangedRegistrants.notifyResult( 186 SatelliteServiceUtils.fromSatelliteCapabilities(satelliteCapabilities)); 187 } 188 189 @Override onSatelliteSupportedStateChanged(boolean supported)190 public void onSatelliteSupportedStateChanged(boolean supported) { 191 mSatelliteSupportedStateChangedRegistrants.notifyResult(supported); 192 } 193 194 @Override onRegistrationFailure(int causeCode)195 public void onRegistrationFailure(int causeCode) { 196 // TO-DO notify registrants 197 } 198 notifyResultIfExpectedListener()199 private boolean notifyResultIfExpectedListener() { 200 // Demo listener should notify results only during demo mode 201 // Vendor listener should notify result only during real mode 202 return mIsDemoListener == mSatelliteController.isDemoModeEnabled(); 203 } 204 notifyModemStateChanged(int state)205 private boolean notifyModemStateChanged(int state) { 206 if (notifyResultIfExpectedListener()) { 207 return true; 208 } 209 210 return state == SatelliteModemState.SATELLITE_MODEM_STATE_OFF 211 || state == SatelliteModemState.SATELLITE_MODEM_STATE_UNAVAILABLE; 212 } 213 } 214 215 /** 216 * @return The singleton instance of SatelliteModemInterface. 217 */ getInstance()218 public static SatelliteModemInterface getInstance() { 219 if (sInstance == null) { 220 loge("SatelliteModemInterface was not yet initialized."); 221 } 222 return sInstance; 223 } 224 225 /** 226 * Create the SatelliteModemInterface singleton instance. 227 * @param context The Context to use to create the SatelliteModemInterface. 228 * @param satelliteController The singleton instance of SatelliteController. 229 * @param featureFlags The telephony feature flags. 230 * @return The singleton instance of SatelliteModemInterface. 231 */ make(@onNull Context context, SatelliteController satelliteController, @NonNull FeatureFlags featureFlags)232 public static SatelliteModemInterface make(@NonNull Context context, 233 SatelliteController satelliteController, 234 @NonNull FeatureFlags featureFlags) { 235 if (sInstance == null) { 236 sInstance = new SatelliteModemInterface( 237 context, satelliteController, Looper.getMainLooper(), featureFlags); 238 } 239 return sInstance; 240 } 241 242 /** 243 * Create a SatelliteModemInterface to manage connections to the SatelliteService. 244 * 245 * @param context The Context for the SatelliteModemInterface. 246 * @param featureFlags The telephony feature flags. 247 * @param looper The Looper to run binding retry on. 248 */ 249 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) SatelliteModemInterface(@onNull Context context, SatelliteController satelliteController, @NonNull Looper looper, @NonNull FeatureFlags featureFlags)250 protected SatelliteModemInterface(@NonNull Context context, 251 SatelliteController satelliteController, 252 @NonNull Looper looper, 253 @NonNull FeatureFlags featureFlags) { 254 if (isSatellitePersistentLoggingEnabled(context, featureFlags)) { 255 mPersistentLogger = new PersistentLogger( 256 DropBoxManagerLoggerBackend.getInstance(context)); 257 } 258 mContext = context; 259 mDemoSimulator = DemoSimulator.make(context, satelliteController); 260 mVendorListener = new SatelliteListener(false); 261 mDemoListener = new SatelliteListener(true); 262 mIsSatelliteServiceSupported = getSatelliteServiceSupport(); 263 mSatelliteController = satelliteController; 264 mExponentialBackoff = new ExponentialBackoff(REBIND_INITIAL_DELAY, REBIND_MAXIMUM_DELAY, 265 REBIND_MULTIPLIER, looper, () -> { 266 synchronized (mLock) { 267 if ((mIsBound && mSatelliteService != null) || mIsBinding) { 268 return; 269 } 270 } 271 if (mSatelliteServiceConnection != null) { 272 synchronized (mLock) { 273 mIsBound = false; 274 mIsBinding = false; 275 } 276 unbindService(); 277 } 278 bindService(); 279 }); 280 mExponentialBackoff.start(); 281 plogd("Created SatelliteModemInterface. Attempting to bind to SatelliteService."); 282 bindService(); 283 } 284 285 /** 286 * Get the SatelliteService interface, if it exists. 287 * 288 * @return The bound ISatellite, or {@code null} if it is not yet connected. 289 */ getService()290 @Nullable public ISatellite getService() { 291 return mSatelliteService; 292 } 293 getSatellitePackageName()294 @NonNull private String getSatellitePackageName() { 295 if (!TextUtils.isEmpty(mVendorSatellitePackageName)) { 296 return mVendorSatellitePackageName; 297 } 298 return TextUtils.emptyIfNull(mContext.getResources().getString( 299 R.string.config_satellite_service_package)); 300 } 301 getSatelliteServiceSupport()302 private boolean getSatelliteServiceSupport() { 303 return !TextUtils.isEmpty(getSatellitePackageName()); 304 } 305 306 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) bindService()307 protected void bindService() { 308 synchronized (mLock) { 309 if (mIsBinding || mIsBound) return; 310 mIsBinding = true; 311 } 312 String packageName = getSatellitePackageName(); 313 if (TextUtils.isEmpty(packageName)) { 314 ploge("Unable to bind to the satellite service because the package is undefined."); 315 // Since the package name comes from static device configs, stop retry because 316 // rebind will continue to fail without a valid package name. 317 synchronized (mLock) { 318 mIsBinding = false; 319 } 320 mExponentialBackoff.stop(); 321 return; 322 } 323 Intent intent = new Intent(SatelliteService.SERVICE_INTERFACE); 324 intent.setPackage(packageName); 325 326 mSatelliteServiceConnection = new SatelliteServiceConnection(); 327 plogd("Binding to " + packageName); 328 try { 329 boolean success = mContext.bindService( 330 intent, mSatelliteServiceConnection, Context.BIND_AUTO_CREATE); 331 if (success) { 332 plogd("Successfully bound to the satellite service."); 333 } else { 334 synchronized (mLock) { 335 mIsBinding = false; 336 } 337 mExponentialBackoff.notifyFailed(); 338 ploge("Error binding to the satellite service. Retrying in " 339 + mExponentialBackoff.getCurrentDelay() + " ms."); 340 } 341 } catch (Exception e) { 342 synchronized (mLock) { 343 mIsBinding = false; 344 } 345 mExponentialBackoff.notifyFailed(); 346 ploge("Exception binding to the satellite service. Retrying in " 347 + mExponentialBackoff.getCurrentDelay() + " ms. Exception: " + e); 348 } 349 } 350 351 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) unbindService()352 protected void unbindService() { 353 disconnectSatelliteService(); 354 mContext.unbindService(mSatelliteServiceConnection); 355 mSatelliteServiceConnection = null; 356 } 357 disconnectSatelliteService()358 private void disconnectSatelliteService() { 359 // TODO: clean up any listeners and return failed for pending callbacks 360 mSatelliteService = null; 361 } 362 363 private class SatelliteServiceConnection implements ServiceConnection { 364 @Override onServiceConnected(ComponentName name, IBinder service)365 public void onServiceConnected(ComponentName name, IBinder service) { 366 plogd("onServiceConnected: ComponentName=" + name); 367 synchronized (mLock) { 368 mIsBound = true; 369 mIsBinding = false; 370 } 371 mSatelliteService = ISatellite.Stub.asInterface(service); 372 mExponentialBackoff.stop(); 373 try { 374 mSatelliteService.setSatelliteListener(mVendorListener); 375 mDemoSimulator.setSatelliteListener(mDemoListener); 376 } catch (RemoteException e) { 377 // TODO: Retry setSatelliteListener 378 plogd("setSatelliteListener: RemoteException " + e); 379 } 380 mSatelliteController.onSatelliteServiceConnected(); 381 } 382 383 @Override onServiceDisconnected(ComponentName name)384 public void onServiceDisconnected(ComponentName name) { 385 ploge("onServiceDisconnected: Waiting for reconnect."); 386 synchronized (mLock) { 387 mIsBinding = false; 388 } 389 // Since we are still technically bound, clear the service and wait for reconnect. 390 disconnectSatelliteService(); 391 } 392 393 @Override onBindingDied(ComponentName name)394 public void onBindingDied(ComponentName name) { 395 ploge("onBindingDied: Unbinding and rebinding service."); 396 synchronized (mLock) { 397 mIsBound = false; 398 mIsBinding = false; 399 } 400 unbindService(); 401 mExponentialBackoff.start(); 402 } 403 } 404 405 /** 406 * Registers for the satellite provision state changed. 407 * 408 * @param h Handler for notification message. 409 * @param what User-defined message code. 410 * @param obj User object. 411 */ registerForSatelliteProvisionStateChanged( @onNull Handler h, int what, @Nullable Object obj)412 public void registerForSatelliteProvisionStateChanged( 413 @NonNull Handler h, int what, @Nullable Object obj) { 414 mSatelliteProvisionStateChangedRegistrants.add(h, what, obj); 415 } 416 417 /** 418 * Unregisters for the satellite provision state changed. 419 * 420 * @param h Handler to be removed from the registrant list. 421 */ unregisterForSatelliteProvisionStateChanged(@onNull Handler h)422 public void unregisterForSatelliteProvisionStateChanged(@NonNull Handler h) { 423 mSatelliteProvisionStateChangedRegistrants.remove(h); 424 } 425 426 /** 427 * Registers for satellite position info changed from satellite modem. 428 * 429 * @param h Handler for notification message. 430 * @param what User-defined message code. 431 * @param obj User object. 432 */ registerForSatellitePositionInfoChanged( @onNull Handler h, int what, @Nullable Object obj)433 public void registerForSatellitePositionInfoChanged( 434 @NonNull Handler h, int what, @Nullable Object obj) { 435 mSatellitePositionInfoChangedRegistrants.add(h, what, obj); 436 } 437 438 /** 439 * Unregisters for satellite position info changed from satellite modem. 440 * 441 * @param h Handler to be removed from the registrant list. 442 */ unregisterForSatellitePositionInfoChanged(@onNull Handler h)443 public void unregisterForSatellitePositionInfoChanged(@NonNull Handler h) { 444 mSatellitePositionInfoChangedRegistrants.remove(h); 445 } 446 447 /** 448 * Registers for datagram transfer state changed. 449 * 450 * @param h Handler for notification message. 451 * @param what User-defined message code. 452 * @param obj User object. 453 */ registerForDatagramTransferStateChanged( @onNull Handler h, int what, @Nullable Object obj)454 public void registerForDatagramTransferStateChanged( 455 @NonNull Handler h, int what, @Nullable Object obj) { 456 mDatagramTransferStateChangedRegistrants.add(h, what, obj); 457 } 458 459 /** 460 * Unregisters for datagram transfer state changed. 461 * 462 * @param h Handler to be removed from the registrant list. 463 */ unregisterForDatagramTransferStateChanged(@onNull Handler h)464 public void unregisterForDatagramTransferStateChanged(@NonNull Handler h) { 465 mDatagramTransferStateChangedRegistrants.remove(h); 466 } 467 468 /** 469 * Registers for modem state changed from satellite modem. 470 * 471 * @param h Handler for notification message. 472 * @param what User-defined message code. 473 * @param obj User object. 474 */ registerForSatelliteModemStateChanged( @onNull Handler h, int what, @Nullable Object obj)475 public void registerForSatelliteModemStateChanged( 476 @NonNull Handler h, int what, @Nullable Object obj) { 477 mSatelliteModemStateChangedRegistrants.add(h, what, obj); 478 } 479 480 /** 481 * Unregisters for modem state changed from satellite modem. 482 * 483 * @param h Handler to be removed from the registrant list. 484 */ unregisterForSatelliteModemStateChanged(@onNull Handler h)485 public void unregisterForSatelliteModemStateChanged(@NonNull Handler h) { 486 mSatelliteModemStateChangedRegistrants.remove(h); 487 } 488 489 /** 490 * Registers for pending datagrams indication from satellite modem. 491 * 492 * @param h Handler for notification message. 493 * @param what User-defined message code. 494 * @param obj User object. 495 */ registerForPendingDatagrams(@onNull Handler h, int what, @Nullable Object obj)496 public void registerForPendingDatagrams(@NonNull Handler h, int what, @Nullable Object obj) { 497 mPendingDatagramsRegistrants.add(h, what, obj); 498 } 499 500 /** 501 * Unregisters for pending datagrams indication from satellite modem. 502 * 503 * @param h Handler to be removed from the registrant list. 504 */ unregisterForPendingDatagrams(@onNull Handler h)505 public void unregisterForPendingDatagrams(@NonNull Handler h) { 506 mPendingDatagramsRegistrants.remove(h); 507 } 508 509 /** 510 * Registers for new datagrams received from satellite modem. 511 * 512 * @param h Handler for notification message. 513 * @param what User-defined message code. 514 * @param obj User object. 515 */ registerForSatelliteDatagramsReceived( @onNull Handler h, int what, @Nullable Object obj)516 public void registerForSatelliteDatagramsReceived( 517 @NonNull Handler h, int what, @Nullable Object obj) { 518 mSatelliteDatagramsReceivedRegistrants.add(h, what, obj); 519 } 520 521 /** 522 * Unregisters for new datagrams received from satellite modem. 523 * 524 * @param h Handler to be removed from the registrant list. 525 */ unregisterForSatelliteDatagramsReceived(@onNull Handler h)526 public void unregisterForSatelliteDatagramsReceived(@NonNull Handler h) { 527 mSatelliteDatagramsReceivedRegistrants.remove(h); 528 } 529 530 /** 531 * Registers for non-terrestrial signal strength level changed. 532 * 533 * @param h Handler for notification message. 534 * @param what User-defined message code. 535 * @param obj User object. 536 */ registerForNtnSignalStrengthChanged( @onNull Handler h, int what, @Nullable Object obj)537 public void registerForNtnSignalStrengthChanged( 538 @NonNull Handler h, int what, @Nullable Object obj) { 539 mNtnSignalStrengthChangedRegistrants.add(h, what, obj); 540 } 541 542 /** 543 * Unregisters for non-terrestrial signal strength level changed. 544 * 545 * @param h Handler to be removed from the registrant list. 546 */ unregisterForNtnSignalStrengthChanged(@onNull Handler h)547 public void unregisterForNtnSignalStrengthChanged(@NonNull Handler h) { 548 mNtnSignalStrengthChangedRegistrants.remove(h); 549 } 550 551 /** 552 * Registers for satellite capabilities changed. 553 * 554 * @param h Handler for notification message. 555 * @param what User-defined message code. 556 * @param obj User object. 557 */ registerForSatelliteCapabilitiesChanged( @onNull Handler h, int what, @Nullable Object obj)558 public void registerForSatelliteCapabilitiesChanged( 559 @NonNull Handler h, int what, @Nullable Object obj) { 560 mSatelliteCapabilitiesChangedRegistrants.add(h, what, obj); 561 } 562 563 /** 564 * Unregisters for satellite capabilities changed. 565 * 566 * @param h Handler to be removed from the registrant list. 567 */ unregisterForSatelliteCapabilitiesChanged(@onNull Handler h)568 public void unregisterForSatelliteCapabilitiesChanged(@NonNull Handler h) { 569 mSatelliteCapabilitiesChangedRegistrants.remove(h); 570 } 571 572 /** 573 * Registers for the satellite supported state changed. 574 * 575 * @param h Handler for notification message. 576 * @param what User-defined message code. 577 * @param obj User object. 578 */ registerForSatelliteSupportedStateChanged( @onNull Handler h, int what, @Nullable Object obj)579 public void registerForSatelliteSupportedStateChanged( 580 @NonNull Handler h, int what, @Nullable Object obj) { 581 mSatelliteSupportedStateChangedRegistrants.add(h, what, obj); 582 } 583 584 /** 585 * Unregisters for the satellite supported state changed. 586 * 587 * @param h Handler to be removed from the registrant list. 588 */ unregisterForSatelliteSupportedStateChanged(@onNull Handler h)589 public void unregisterForSatelliteSupportedStateChanged(@NonNull Handler h) { 590 mSatelliteSupportedStateChangedRegistrants.remove(h); 591 } 592 593 /** 594 * Request to enable or disable the satellite service listening mode. 595 * Listening mode allows the satellite service to listen for incoming pages. 596 * 597 * @param enable True to enable satellite listening mode and false to disable. 598 * @param timeout How long the satellite modem should wait for the next incoming page before 599 * disabling listening mode. 600 * @param message The Message to send to result of the operation to. 601 */ requestSatelliteListeningEnabled(boolean enable, int timeout, @Nullable Message message)602 public void requestSatelliteListeningEnabled(boolean enable, int timeout, 603 @Nullable Message message) { 604 if (mSatelliteService != null) { 605 try { 606 mSatelliteService.requestSatelliteListeningEnabled(enable, timeout, 607 new IIntegerConsumer.Stub() { 608 @Override 609 public void accept(int result) { 610 int error = SatelliteServiceUtils.fromSatelliteError(result); 611 plogd("requestSatelliteListeningEnabled: " + error); 612 Binder.withCleanCallingIdentity(() -> { 613 if (message != null) { 614 sendMessageWithResult(message, null, error); 615 } 616 }); 617 } 618 }); 619 } catch (RemoteException e) { 620 ploge("requestSatelliteListeningEnabled: RemoteException " + e); 621 if (message != null) { 622 sendMessageWithResult( 623 message, null, SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 624 } 625 } 626 } else { 627 ploge("requestSatelliteListeningEnabled: Satellite service is unavailable."); 628 if (message != null) { 629 sendMessageWithResult(message, null, 630 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 631 } 632 } 633 } 634 635 /** 636 * Allow cellular modem scanning while satellite mode is on. 637 * @param enabled {@code true} to enable cellular modem while satellite mode is on 638 * and {@code false} to disable 639 * @param message The Message to send to result of the operation to. 640 */ enableCellularModemWhileSatelliteModeIsOn(boolean enabled, @Nullable Message message)641 public void enableCellularModemWhileSatelliteModeIsOn(boolean enabled, 642 @Nullable Message message) { 643 if (mSatelliteService != null) { 644 try { 645 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 646 @Override 647 public void accept(int result) { 648 int error = SatelliteServiceUtils.fromSatelliteError(result); 649 plogd("enableCellularModemWhileSatelliteModeIsOn: " + error); 650 Binder.withCleanCallingIdentity(() -> { 651 if (message != null) { 652 sendMessageWithResult(message, null, error); 653 } 654 }); 655 } 656 }; 657 658 if (mSatelliteController.isDemoModeEnabled()) { 659 mDemoSimulator.enableCellularModemWhileSatelliteModeIsOn( 660 enabled, errorCallback); 661 } else { 662 mSatelliteService.enableCellularModemWhileSatelliteModeIsOn( 663 enabled, errorCallback); 664 } 665 } catch (RemoteException e) { 666 ploge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e); 667 if (message != null) { 668 sendMessageWithResult( 669 message, null, SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 670 } 671 } 672 } else { 673 ploge("enableCellularModemWhileSatelliteModeIsOn: Satellite service is unavailable."); 674 if (message != null) { 675 sendMessageWithResult(message, null, 676 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 677 } 678 } 679 } 680 /** 681 * Request to enable or disable the satellite modem and demo mode. If the satellite modem 682 * is enabled, this may also disable the cellular modem, and if the satellite modem is disabled, 683 * this may also re-enable the cellular modem. 684 * 685 * @param enableSatellite True to enable the satellite modem and false to disable. 686 * @param enableDemoMode True to enable demo mode and false to disable. 687 * @param isEmergency {@code true} to enable emergency mode, {@code false} otherwise. 688 * @param message The Message to send to result of the operation to. 689 */ requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode, boolean isEmergency, @NonNull Message message)690 public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode, 691 boolean isEmergency, @NonNull Message message) { 692 if (mSatelliteService != null) { 693 try { 694 mSatelliteService.requestSatelliteEnabled(enableSatellite, enableDemoMode, 695 isEmergency, new IIntegerConsumer.Stub() { 696 @Override 697 public void accept(int result) { 698 int error = SatelliteServiceUtils.fromSatelliteError(result); 699 plogd("setSatelliteEnabled: " + error); 700 Binder.withCleanCallingIdentity(() -> 701 sendMessageWithResult(message, null, error)); 702 } 703 }); 704 } catch (RemoteException e) { 705 ploge("setSatelliteEnabled: RemoteException " + e); 706 sendMessageWithResult(message, null, 707 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 708 } 709 } else { 710 ploge("setSatelliteEnabled: Satellite service is unavailable."); 711 sendMessageWithResult(message, null, 712 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 713 } 714 } 715 716 /** 717 * Request to get whether the satellite modem is enabled. 718 * 719 * @param message The Message to send to result of the operation to. 720 */ requestIsSatelliteEnabled(@onNull Message message)721 public void requestIsSatelliteEnabled(@NonNull Message message) { 722 if (mSatelliteService != null) { 723 try { 724 mSatelliteService.requestIsSatelliteEnabled(new IIntegerConsumer.Stub() { 725 @Override 726 public void accept(int result) { 727 int error = SatelliteServiceUtils.fromSatelliteError(result); 728 plogd("requestIsSatelliteEnabled: " + error); 729 Binder.withCleanCallingIdentity(() -> 730 sendMessageWithResult(message, null, error)); 731 } 732 }, new IBooleanConsumer.Stub() { 733 @Override 734 public void accept(boolean result) { 735 // Convert for compatibility with SatelliteResponse 736 // TODO: This should just report result instead. 737 int[] enabled = new int[] {result ? 1 : 0}; 738 plogd("requestIsSatelliteEnabled: " + Arrays.toString(enabled)); 739 Binder.withCleanCallingIdentity(() -> sendMessageWithResult( 740 message, enabled, SatelliteManager.SATELLITE_RESULT_SUCCESS)); 741 } 742 }); 743 } catch (RemoteException e) { 744 ploge("requestIsSatelliteEnabled: RemoteException " + e); 745 sendMessageWithResult(message, null, 746 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 747 } 748 } else { 749 ploge("requestIsSatelliteEnabled: Satellite service is unavailable."); 750 sendMessageWithResult(message, null, 751 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 752 } 753 } 754 755 /** 756 * Request to get whether the satellite service is supported on the device. 757 * 758 * @param message The Message to send to result of the operation to. 759 */ requestIsSatelliteSupported(@onNull Message message)760 public void requestIsSatelliteSupported(@NonNull Message message) { 761 if (mSatelliteService != null) { 762 try { 763 mSatelliteService.requestIsSatelliteSupported(new IIntegerConsumer.Stub() { 764 @Override 765 public void accept(int result) { 766 int error = SatelliteServiceUtils.fromSatelliteError(result); 767 plogd("requestIsSatelliteSupported: " + error); 768 Binder.withCleanCallingIdentity(() -> 769 sendMessageWithResult(message, null, error)); 770 } 771 }, new IBooleanConsumer.Stub() { 772 @Override 773 public void accept(boolean result) { 774 plogd("requestIsSatelliteSupported: " + result); 775 Binder.withCleanCallingIdentity(() -> sendMessageWithResult( 776 message, result, SatelliteManager.SATELLITE_RESULT_SUCCESS)); 777 } 778 }); 779 } catch (RemoteException e) { 780 ploge("requestIsSatelliteSupported: RemoteException " + e); 781 sendMessageWithResult(message, null, 782 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 783 } 784 } else { 785 ploge("requestIsSatelliteSupported: Satellite service is unavailable."); 786 sendMessageWithResult( 787 message, null, SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 788 } 789 } 790 791 /** 792 * Request to get the SatelliteCapabilities of the satellite service. 793 * 794 * @param message The Message to send to result of the operation to. 795 */ requestSatelliteCapabilities(@onNull Message message)796 public void requestSatelliteCapabilities(@NonNull Message message) { 797 if (mSatelliteService != null) { 798 try { 799 mSatelliteService.requestSatelliteCapabilities(new IIntegerConsumer.Stub() { 800 @Override 801 public void accept(int result) { 802 int error = SatelliteServiceUtils.fromSatelliteError(result); 803 plogd("requestSatelliteCapabilities: " + error); 804 Binder.withCleanCallingIdentity(() -> 805 sendMessageWithResult(message, null, error)); 806 } 807 }, new ISatelliteCapabilitiesConsumer.Stub() { 808 @Override 809 public void accept(android.telephony.satellite.stub.SatelliteCapabilities 810 result) { 811 SatelliteCapabilities capabilities = 812 SatelliteServiceUtils.fromSatelliteCapabilities(result); 813 plogd("requestSatelliteCapabilities: " + capabilities); 814 Binder.withCleanCallingIdentity(() -> sendMessageWithResult( 815 message, capabilities, SatelliteManager.SATELLITE_RESULT_SUCCESS)); 816 } 817 }); 818 } catch (RemoteException e) { 819 ploge("requestSatelliteCapabilities: RemoteException " + e); 820 sendMessageWithResult(message, null, 821 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 822 } 823 } else { 824 ploge("requestSatelliteCapabilities: Satellite service is unavailable."); 825 sendMessageWithResult(message, null, 826 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 827 } 828 } 829 830 /** 831 * User started pointing to the satellite. 832 * The satellite service should report the satellite pointing info via 833 * ISatelliteListener#onSatellitePositionChanged as the user device/satellite moves. 834 * 835 * @param message The Message to send to result of the operation to. 836 */ startSendingSatellitePointingInfo(@onNull Message message)837 public void startSendingSatellitePointingInfo(@NonNull Message message) { 838 if (mSatelliteService != null) { 839 try { 840 mSatelliteService.startSendingSatellitePointingInfo(new IIntegerConsumer.Stub() { 841 @Override 842 public void accept(int result) { 843 int error = SatelliteServiceUtils.fromSatelliteError(result); 844 plogd("startSendingSatellitePointingInfo: " + error); 845 Binder.withCleanCallingIdentity(() -> 846 sendMessageWithResult(message, null, error)); 847 } 848 }); 849 } catch (RemoteException e) { 850 ploge("startSendingSatellitePointingInfo: RemoteException " + e); 851 sendMessageWithResult(message, null, 852 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 853 } 854 } else { 855 ploge("startSendingSatellitePointingInfo: Satellite service is unavailable."); 856 sendMessageWithResult(message, null, 857 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 858 } 859 } 860 861 /** 862 * User stopped pointing to the satellite. 863 * The satellite service should stop reporting satellite pointing info to the framework. 864 * 865 * @param message The Message to send to result of the operation to. 866 */ stopSendingSatellitePointingInfo(@onNull Message message)867 public void stopSendingSatellitePointingInfo(@NonNull Message message) { 868 if (mSatelliteService != null) { 869 try { 870 mSatelliteService.stopSendingSatellitePointingInfo(new IIntegerConsumer.Stub() { 871 @Override 872 public void accept(int result) { 873 int error = SatelliteServiceUtils.fromSatelliteError(result); 874 plogd("stopSendingSatellitePointingInfo: " + error); 875 Binder.withCleanCallingIdentity(() -> 876 sendMessageWithResult(message, null, error)); 877 } 878 }); 879 } catch (RemoteException e) { 880 ploge("stopSendingSatellitePointingInfo: RemoteException " + e); 881 sendMessageWithResult(message, null, 882 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 883 } 884 } else { 885 ploge("stopSendingSatellitePointingInfo: Satellite service is unavailable."); 886 sendMessageWithResult(message, null, 887 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 888 } 889 } 890 891 /** 892 * Provision the device with a satellite provider. 893 * This is needed if the provider allows dynamic registration. 894 * Once provisioned, ISatelliteListener#onSatelliteProvisionStateChanged should report true. 895 * 896 * @param token The token to be used as a unique identifier for provisioning with satellite 897 * gateway. 898 * @param provisionData Data from the provisioning app that can be used by provisioning server 899 * @param message The Message to send to result of the operation to. 900 */ provisionSatelliteService(@onNull String token, @NonNull byte[] provisionData, @NonNull Message message)901 public void provisionSatelliteService(@NonNull String token, @NonNull byte[] provisionData, 902 @NonNull Message message) { 903 if (mSatelliteService != null) { 904 try { 905 mSatelliteService.provisionSatelliteService(token, provisionData, 906 new IIntegerConsumer.Stub() { 907 @Override 908 public void accept(int result) { 909 int error = SatelliteServiceUtils.fromSatelliteError(result); 910 plogd("provisionSatelliteService: " + error); 911 Binder.withCleanCallingIdentity(() -> 912 sendMessageWithResult(message, null, error)); 913 } 914 }); 915 } catch (RemoteException e) { 916 ploge("provisionSatelliteService: RemoteException " + e); 917 sendMessageWithResult(message, null, 918 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 919 } 920 } else { 921 ploge("provisionSatelliteService: Satellite service is unavailable."); 922 sendMessageWithResult(message, null, 923 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 924 } 925 } 926 927 /** 928 * Deprovision the device with the satellite provider. 929 * This is needed if the provider allows dynamic registration. 930 * Once deprovisioned, ISatelliteListener#onSatelliteProvisionStateChanged should report false. 931 * 932 * @param token The token of the device/subscription to be deprovisioned. 933 * @param message The Message to send to result of the operation to. 934 */ deprovisionSatelliteService(@onNull String token, @NonNull Message message)935 public void deprovisionSatelliteService(@NonNull String token, @NonNull Message message) { 936 if (mSatelliteService != null) { 937 try { 938 mSatelliteService.deprovisionSatelliteService(token, new IIntegerConsumer.Stub() { 939 @Override 940 public void accept(int result) { 941 int error = SatelliteServiceUtils.fromSatelliteError(result); 942 plogd("deprovisionSatelliteService: " + error); 943 Binder.withCleanCallingIdentity(() -> 944 sendMessageWithResult(message, null, error)); 945 } 946 }); 947 } catch (RemoteException e) { 948 ploge("deprovisionSatelliteService: RemoteException " + e); 949 sendMessageWithResult(message, null, 950 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 951 } 952 } else { 953 ploge("deprovisionSatelliteService: Satellite service is unavailable."); 954 sendMessageWithResult(message, null, 955 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 956 } 957 } 958 959 /** 960 * Request to get whether this device is provisioned with a satellite provider. 961 * 962 * @param message The Message to send to result of the operation to. 963 */ requestIsSatelliteProvisioned(@onNull Message message)964 public void requestIsSatelliteProvisioned(@NonNull Message message) { 965 if (mSatelliteService != null) { 966 try { 967 mSatelliteService.requestIsSatelliteProvisioned(new IIntegerConsumer.Stub() { 968 @Override 969 public void accept(int result) { 970 int error = SatelliteServiceUtils.fromSatelliteError(result); 971 plogd("requestIsSatelliteProvisioned: " + error); 972 Binder.withCleanCallingIdentity(() -> 973 sendMessageWithResult(message, null, error)); 974 } 975 }, new IBooleanConsumer.Stub() { 976 @Override 977 public void accept(boolean result) { 978 // Convert for compatibility with SatelliteResponse 979 // TODO: This should just report result instead. 980 int[] provisioned = new int[] {result ? 1 : 0}; 981 plogd("requestIsSatelliteProvisioned: " + Arrays.toString(provisioned)); 982 Binder.withCleanCallingIdentity(() -> sendMessageWithResult( 983 message, provisioned, SatelliteManager.SATELLITE_RESULT_SUCCESS)); 984 } 985 }); 986 } catch (RemoteException e) { 987 ploge("requestIsSatelliteProvisioned: RemoteException " + e); 988 sendMessageWithResult(message, null, 989 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 990 } 991 } else { 992 ploge("requestIsSatelliteProvisioned: Satellite service is unavailable."); 993 sendMessageWithResult(message, null, 994 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 995 } 996 } 997 998 /** 999 * Poll the pending datagrams to be received over satellite. 1000 * The satellite service should check if there are any pending datagrams to be received over 1001 * satellite and report them via ISatelliteListener#onSatelliteDatagramsReceived. 1002 * 1003 * @param message The Message to send to result of the operation to. 1004 */ pollPendingSatelliteDatagrams(@onNull Message message)1005 public void pollPendingSatelliteDatagrams(@NonNull Message message) { 1006 if (mSatelliteService != null) { 1007 try { 1008 mSatelliteService.pollPendingSatelliteDatagrams(new IIntegerConsumer.Stub() { 1009 @Override 1010 public void accept(int result) { 1011 int error = SatelliteServiceUtils.fromSatelliteError(result); 1012 plogd("pollPendingDatagrams: " + error); 1013 Binder.withCleanCallingIdentity(() -> 1014 sendMessageWithResult(message, null, error)); 1015 } 1016 }); 1017 } catch (RemoteException e) { 1018 ploge("pollPendingDatagrams: RemoteException " + e); 1019 sendMessageWithResult(message, null, 1020 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 1021 } 1022 } else { 1023 ploge("pollPendingDatagrams: Satellite service is unavailable."); 1024 sendMessageWithResult(message, null, 1025 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 1026 } 1027 } 1028 1029 /** 1030 * Send datagram over satellite. 1031 * 1032 * @param datagram Datagram to send in byte format. 1033 * @param isEmergency Whether this is an emergency datagram. 1034 * @param needFullScreenPointingUI this is used to indicate pointingUI app to open in 1035 * full screen mode. 1036 * @param message The Message to send to result of the operation to. 1037 */ sendSatelliteDatagram(@onNull SatelliteDatagram datagram, boolean isEmergency, boolean needFullScreenPointingUI, @NonNull Message message)1038 public void sendSatelliteDatagram(@NonNull SatelliteDatagram datagram, boolean isEmergency, 1039 boolean needFullScreenPointingUI, @NonNull Message message) { 1040 if (mSatelliteService != null) { 1041 try { 1042 mSatelliteService.sendSatelliteDatagram( 1043 SatelliteServiceUtils.toSatelliteDatagram(datagram), isEmergency, 1044 new IIntegerConsumer.Stub() { 1045 @Override 1046 public void accept(int result) { 1047 int error = SatelliteServiceUtils.fromSatelliteError(result); 1048 plogd("sendDatagram: " + error); 1049 Binder.withCleanCallingIdentity(() -> 1050 sendMessageWithResult(message, null, error)); 1051 } 1052 }); 1053 } catch (RemoteException e) { 1054 ploge("sendDatagram: RemoteException " + e); 1055 sendMessageWithResult(message, null, 1056 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 1057 } 1058 } else { 1059 ploge("sendDatagram: Satellite service is unavailable."); 1060 sendMessageWithResult(message, null, 1061 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 1062 } 1063 } 1064 1065 /** 1066 * Request the current satellite modem state. 1067 * The satellite service should report the current satellite modem state via 1068 * ISatelliteListener#onSatelliteModemStateChanged. 1069 * 1070 * @param message The Message to send to result of the operation to. 1071 */ requestSatelliteModemState(@onNull Message message)1072 public void requestSatelliteModemState(@NonNull Message message) { 1073 if (mSatelliteService != null) { 1074 try { 1075 mSatelliteService.requestSatelliteModemState(new IIntegerConsumer.Stub() { 1076 @Override 1077 public void accept(int result) { 1078 int error = SatelliteServiceUtils.fromSatelliteError(result); 1079 plogd("requestSatelliteModemState: " + error); 1080 Binder.withCleanCallingIdentity(() -> 1081 sendMessageWithResult(message, null, error)); 1082 } 1083 }, new IIntegerConsumer.Stub() { 1084 @Override 1085 public void accept(int result) { 1086 // Convert SatelliteModemState from service to frameworks definition. 1087 int modemState = SatelliteServiceUtils.fromSatelliteModemState(result); 1088 plogd("requestSatelliteModemState: " + modemState); 1089 Binder.withCleanCallingIdentity(() -> sendMessageWithResult( 1090 message, modemState, SatelliteManager.SATELLITE_RESULT_SUCCESS)); 1091 } 1092 }); 1093 } catch (RemoteException e) { 1094 ploge("requestSatelliteModemState: RemoteException " + e); 1095 sendMessageWithResult(message, null, 1096 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 1097 } 1098 } else { 1099 ploge("requestSatelliteModemState: Satellite service is unavailable."); 1100 sendMessageWithResult(message, null, 1101 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 1102 } 1103 } 1104 1105 /** 1106 * Request to get the time after which the satellite will be visible. This is an int 1107 * representing the duration in seconds after which the satellite will be visible. 1108 * This will return 0 if the satellite is currently visible. 1109 * 1110 * @param message The Message to send to result of the operation to. 1111 */ requestTimeForNextSatelliteVisibility(@onNull Message message)1112 public void requestTimeForNextSatelliteVisibility(@NonNull Message message) { 1113 if (mSatelliteService != null) { 1114 try { 1115 mSatelliteService.requestTimeForNextSatelliteVisibility( 1116 new IIntegerConsumer.Stub() { 1117 @Override 1118 public void accept(int result) { 1119 int error = SatelliteServiceUtils.fromSatelliteError(result); 1120 plogd("requestTimeForNextSatelliteVisibility: " + error); 1121 Binder.withCleanCallingIdentity(() -> 1122 sendMessageWithResult(message, null, error)); 1123 } 1124 }, new IIntegerConsumer.Stub() { 1125 @Override 1126 public void accept(int result) { 1127 // Convert for compatibility with SatelliteResponse 1128 // TODO: This should just report result instead. 1129 int[] time = new int[] {result}; 1130 plogd("requestTimeForNextSatelliteVisibility: " 1131 + Arrays.toString(time)); 1132 Binder.withCleanCallingIdentity(() -> sendMessageWithResult( 1133 message, time, SatelliteManager.SATELLITE_RESULT_SUCCESS)); 1134 } 1135 }); 1136 } catch (RemoteException e) { 1137 ploge("requestTimeForNextSatelliteVisibility: RemoteException " + e); 1138 sendMessageWithResult(message, null, 1139 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 1140 } 1141 } else { 1142 ploge("requestTimeForNextSatelliteVisibility: Satellite service is unavailable."); 1143 sendMessageWithResult(message, null, 1144 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 1145 } 1146 } 1147 1148 /** 1149 * Set the non-terrestrial PLMN with lower priority than terrestrial networks. 1150 * MCC/MNC broadcast by the non-terrestrial networks will not be included in OPLMNwACT file 1151 * on SIM profile. 1152 * Acquisition of satellite based system is deemed lower priority to terrestrial networks. 1153 * Even so, UE shall make all attempts to acquire terrestrial service prior to camping on 1154 * satellite LTE service. 1155 * 1156 * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use 1157 * this information to determine the relevant carrier. 1158 * @param carrierPlmnList The list of roaming PLMN used for connecting to satellite networks 1159 * supported by user subscription. 1160 * @param allSatellitePlmnList Modem should use the allSatellitePlmnList to identify satellite 1161 * PLMNs that are not supported by the carrier and make sure not to 1162 * attach to them. 1163 * @param message The result receiver that returns whether the modem has 1164 * successfully set the satellite PLMN 1165 */ setSatellitePlmn(@onNull int simSlot, @NonNull List<String> carrierPlmnList, @NonNull List<String> allSatellitePlmnList, @NonNull Message message)1166 public void setSatellitePlmn(@NonNull int simSlot, @NonNull List<String> carrierPlmnList, 1167 @NonNull List<String> allSatellitePlmnList, @NonNull Message message) { 1168 if (mSatelliteService != null) { 1169 try { 1170 mSatelliteService.setSatellitePlmn(simSlot, carrierPlmnList, allSatellitePlmnList, 1171 new IIntegerConsumer.Stub() { 1172 @Override 1173 public void accept(int result) { 1174 int error = SatelliteServiceUtils.fromSatelliteError(result); 1175 plogd("setSatellitePlmn: " + error); 1176 Binder.withCleanCallingIdentity(() -> 1177 sendMessageWithResult(message, null, error)); 1178 } 1179 }); 1180 } catch (RemoteException e) { 1181 ploge("setSatellitePlmn: RemoteException " + e); 1182 sendMessageWithResult(message, null, 1183 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 1184 } 1185 } else { 1186 ploge("setSatellitePlmn: Satellite service is unavailable."); 1187 sendMessageWithResult(message, null, 1188 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 1189 } 1190 } 1191 1192 /** 1193 * Enable or disable satellite in the cellular modem associated with a carrier. 1194 * Refer setSatellitePlmn for the details of satellite PLMN scanning process. 1195 * 1196 * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use 1197 * this information to determine the relevant carrier. 1198 * @param enableSatellite True to enable the satellite modem and false to disable. 1199 * @param message The Message to send to result of the operation to. 1200 */ requestSetSatelliteEnabledForCarrier(@onNull int simSlot, @NonNull boolean enableSatellite, @NonNull Message message)1201 public void requestSetSatelliteEnabledForCarrier(@NonNull int simSlot, 1202 @NonNull boolean enableSatellite, @NonNull Message message) { 1203 if (mSatelliteService != null) { 1204 try { 1205 mSatelliteService.setSatelliteEnabledForCarrier(simSlot, enableSatellite, 1206 new IIntegerConsumer.Stub() { 1207 @Override 1208 public void accept(int result) { 1209 int error = SatelliteServiceUtils.fromSatelliteError(result); 1210 plogd("requestSetSatelliteEnabledForCarrier: " + error); 1211 Binder.withCleanCallingIdentity(() -> 1212 sendMessageWithResult(message, null, error)); 1213 } 1214 }); 1215 } catch (RemoteException e) { 1216 ploge("requestSetSatelliteEnabledForCarrier: RemoteException " + e); 1217 sendMessageWithResult(message, null, 1218 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 1219 } 1220 } else { 1221 ploge("requestSetSatelliteEnabledForCarrier: Satellite service is unavailable."); 1222 sendMessageWithResult(message, null, 1223 SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED); 1224 } 1225 } 1226 1227 /** 1228 * Check whether satellite is enabled in the cellular modem associated with a carrier. 1229 * 1230 * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use 1231 * this information to determine the relevant carrier. 1232 * @param message The Message to send to result of the operation to. 1233 */ requestIsSatelliteEnabledForCarrier(@onNull int simSlot, @NonNull Message message)1234 public void requestIsSatelliteEnabledForCarrier(@NonNull int simSlot, 1235 @NonNull Message message) { 1236 if (mSatelliteService != null) { 1237 try { 1238 mSatelliteService.requestIsSatelliteEnabledForCarrier(simSlot, 1239 new IIntegerConsumer.Stub() { 1240 @Override 1241 public void accept(int result) { 1242 int error = SatelliteServiceUtils.fromSatelliteError(result); 1243 plogd("requestIsSatelliteEnabledForCarrier: " + error); 1244 Binder.withCleanCallingIdentity(() -> 1245 sendMessageWithResult(message, null, error)); 1246 } 1247 }, new IBooleanConsumer.Stub() { 1248 @Override 1249 public void accept(boolean result) { 1250 // Convert for compatibility with SatelliteResponse 1251 // TODO: This should just report result instead. 1252 int[] enabled = new int[] {result ? 1 : 0}; 1253 plogd("requestIsSatelliteEnabledForCarrier: " 1254 + Arrays.toString(enabled)); 1255 Binder.withCleanCallingIdentity(() -> sendMessageWithResult( 1256 message, enabled, 1257 SatelliteManager.SATELLITE_RESULT_SUCCESS)); 1258 } 1259 }); 1260 } catch (RemoteException e) { 1261 ploge("requestIsSatelliteEnabledForCarrier: RemoteException " + e); 1262 sendMessageWithResult(message, null, 1263 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 1264 } 1265 } else { 1266 ploge("requestIsSatelliteEnabledForCarrier: Satellite service is unavailable."); 1267 sendMessageWithResult(message, null, 1268 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 1269 } 1270 } 1271 1272 /** 1273 * Request to get the signal strength of the satellite connection. 1274 * 1275 * @param message The Message to send to result of the operation to. 1276 */ requestNtnSignalStrength(@onNull Message message)1277 public void requestNtnSignalStrength(@NonNull Message message) { 1278 if (mSatelliteService != null) { 1279 try { 1280 mSatelliteService.requestSignalStrength( 1281 new IIntegerConsumer.Stub() { 1282 @Override 1283 public void accept(int result) { 1284 int error = SatelliteServiceUtils.fromSatelliteError(result); 1285 plogd("requestNtnSignalStrength: " + error); 1286 Binder.withCleanCallingIdentity(() -> 1287 sendMessageWithResult(message, null, error)); 1288 } 1289 }, new INtnSignalStrengthConsumer.Stub() { 1290 @Override 1291 public void accept( 1292 android.telephony.satellite.stub.NtnSignalStrength result) { 1293 NtnSignalStrength ntnSignalStrength = 1294 SatelliteServiceUtils.fromNtnSignalStrength(result); 1295 plogd("requestNtnSignalStrength: " + ntnSignalStrength); 1296 Binder.withCleanCallingIdentity(() -> sendMessageWithResult( 1297 message, ntnSignalStrength, 1298 SatelliteManager.SATELLITE_RESULT_SUCCESS)); 1299 } 1300 }); 1301 } catch (RemoteException e) { 1302 ploge("requestNtnSignalStrength: RemoteException " + e); 1303 sendMessageWithResult(message, null, 1304 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 1305 } 1306 } else { 1307 ploge("requestNtnSignalStrength: Satellite service is unavailable."); 1308 sendMessageWithResult(message, null, 1309 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 1310 } 1311 } 1312 1313 /** 1314 * The satellite service should report the NTN signal strength via 1315 * ISatelliteListener#onNtnSignalStrengthChanged when the NTN signal strength changes. 1316 * 1317 * @param message The Message to send to result of the operation to. 1318 */ startSendingNtnSignalStrength(@onNull Message message)1319 public void startSendingNtnSignalStrength(@NonNull Message message) { 1320 if (mSatelliteService != null) { 1321 try { 1322 mSatelliteService.startSendingNtnSignalStrength(new IIntegerConsumer.Stub() { 1323 @Override 1324 public void accept(int result) { 1325 int error = SatelliteServiceUtils.fromSatelliteError(result); 1326 plogd("startSendingNtnSignalStrength: " + error); 1327 Binder.withCleanCallingIdentity(() -> 1328 sendMessageWithResult(message, null, error)); 1329 } 1330 }); 1331 } catch (RemoteException e) { 1332 ploge("startSendingNtnSignalStrength: RemoteException " + e); 1333 sendMessageWithResult(message, null, 1334 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 1335 } 1336 } else { 1337 ploge("startSendingNtnSignalStrength: Satellite service is unavailable."); 1338 sendMessageWithResult(message, null, 1339 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 1340 } 1341 } 1342 1343 /** 1344 * The satellite service should stop reporting NTN signal strength to the framework. 1345 * 1346 * @param message The Message to send to result of the operation to. 1347 */ stopSendingNtnSignalStrength(@onNull Message message)1348 public void stopSendingNtnSignalStrength(@NonNull Message message) { 1349 if (mSatelliteService != null) { 1350 try { 1351 mSatelliteService.stopSendingNtnSignalStrength(new IIntegerConsumer.Stub() { 1352 @Override 1353 public void accept(int result) { 1354 int error = SatelliteServiceUtils.fromSatelliteError(result); 1355 plogd("stopSendingNtnSignalStrength: " + error); 1356 Binder.withCleanCallingIdentity(() -> 1357 sendMessageWithResult(message, null, error)); 1358 } 1359 }); 1360 } catch (RemoteException e) { 1361 ploge("stopSendingNtnSignalStrength: RemoteException " + e); 1362 sendMessageWithResult(message, null, 1363 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 1364 } 1365 } else { 1366 ploge("stopSendingNtnSignalStrength: Satellite service is unavailable."); 1367 sendMessageWithResult(message, null, 1368 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 1369 } 1370 } 1371 1372 /** 1373 * The satellite service should abort all datagram-sending requests. 1374 * 1375 * @param message The Message to send to result of the operation to. 1376 */ abortSendingSatelliteDatagrams(@onNull Message message)1377 public void abortSendingSatelliteDatagrams(@NonNull Message message) { 1378 if (mSatelliteService != null) { 1379 try { 1380 mSatelliteService.abortSendingSatelliteDatagrams(new IIntegerConsumer.Stub() { 1381 @Override 1382 public void accept(int result) { 1383 int error = SatelliteServiceUtils.fromSatelliteError(result); 1384 plogd("abortSendingSatelliteDatagrams: " + error); 1385 Binder.withCleanCallingIdentity(() -> 1386 sendMessageWithResult(message, null, error)); 1387 } 1388 }); 1389 } catch (RemoteException e) { 1390 ploge("abortSendingSatelliteDatagrams: RemoteException " + e); 1391 sendMessageWithResult(message, null, 1392 SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR); 1393 } 1394 } else { 1395 ploge("abortSendingSatelliteDatagrams: Satellite service is unavailable."); 1396 sendMessageWithResult(message, null, 1397 SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE); 1398 } 1399 } 1400 isSatelliteServiceSupported()1401 public boolean isSatelliteServiceSupported() { 1402 return mIsSatelliteServiceSupported; 1403 } 1404 1405 /** Check if vendor satellite service is connected */ isSatelliteServiceConnected()1406 public boolean isSatelliteServiceConnected() { 1407 synchronized (mLock) { 1408 return (mSatelliteService != null); 1409 } 1410 } 1411 1412 /** 1413 * This API can be used by only CTS to update satellite vendor service package name. 1414 * 1415 * @param servicePackageName The package name of the satellite vendor service. 1416 * @return {@code true} if the satellite vendor service is set successfully, 1417 * {@code false} otherwise. 1418 */ 1419 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) setSatelliteServicePackageName(@ullable String servicePackageName)1420 public void setSatelliteServicePackageName(@Nullable String servicePackageName) { 1421 plogd("setSatelliteServicePackageName: config_satellite_service_package is " 1422 + "updated, new packageName=" + servicePackageName); 1423 mExponentialBackoff.stop(); 1424 if (mSatelliteServiceConnection != null) { 1425 synchronized (mLock) { 1426 mIsBound = false; 1427 mIsBinding = false; 1428 } 1429 unbindService(); 1430 } 1431 1432 if (servicePackageName == null || servicePackageName.equals("null")) { 1433 mVendorSatellitePackageName = ""; 1434 } else { 1435 mVendorSatellitePackageName = servicePackageName; 1436 } 1437 mIsSatelliteServiceSupported = getSatelliteServiceSupport(); 1438 bindService(); 1439 mExponentialBackoff.start(); 1440 } 1441 1442 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) sendMessageWithResult(@onNull Message message, @Nullable Object result, @SatelliteManager.SatelliteResult int error)1443 protected static void sendMessageWithResult(@NonNull Message message, @Nullable Object result, 1444 @SatelliteManager.SatelliteResult int error) { 1445 SatelliteException exception = error == SatelliteManager.SATELLITE_RESULT_SUCCESS 1446 ? null : new SatelliteException(error); 1447 AsyncResult.forMessage(message, result, exception); 1448 message.sendToTarget(); 1449 } 1450 logd(@onNull String log)1451 private static void logd(@NonNull String log) { 1452 Rlog.d(TAG, log); 1453 } 1454 loge(@onNull String log)1455 private static void loge(@NonNull String log) { 1456 Rlog.e(TAG, log); 1457 } 1458 isSatellitePersistentLoggingEnabled( @onNull Context context, @NonNull FeatureFlags featureFlags)1459 private boolean isSatellitePersistentLoggingEnabled( 1460 @NonNull Context context, @NonNull FeatureFlags featureFlags) { 1461 if (featureFlags.satellitePersistentLogging()) { 1462 return true; 1463 } 1464 try { 1465 return context.getResources().getBoolean( 1466 R.bool.config_dropboxmanager_persistent_logging_enabled); 1467 } catch (RuntimeException e) { 1468 return false; 1469 } 1470 } 1471 plogd(@onNull String log)1472 private void plogd(@NonNull String log) { 1473 Rlog.d(TAG, log); 1474 if (mPersistentLogger != null) { 1475 mPersistentLogger.debug(TAG, log); 1476 } 1477 } 1478 ploge(@onNull String log)1479 private void ploge(@NonNull String log) { 1480 Rlog.e(TAG, log); 1481 if (mPersistentLogger != null) { 1482 mPersistentLogger.error(TAG, log); 1483 } 1484 } 1485 } 1486