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.Rlog; 34 import android.telephony.satellite.SatelliteCapabilities; 35 import android.telephony.satellite.SatelliteDatagram; 36 import android.telephony.satellite.SatelliteManager; 37 import android.telephony.satellite.SatelliteManager.SatelliteException; 38 import android.telephony.satellite.stub.ISatellite; 39 import android.telephony.satellite.stub.ISatelliteCapabilitiesConsumer; 40 import android.telephony.satellite.stub.ISatelliteListener; 41 import android.telephony.satellite.stub.SatelliteService; 42 import android.text.TextUtils; 43 import android.util.Pair; 44 45 import com.android.internal.R; 46 import com.android.internal.annotations.VisibleForTesting; 47 import com.android.internal.telephony.ExponentialBackoff; 48 import com.android.internal.telephony.IBooleanConsumer; 49 import com.android.internal.telephony.IIntegerConsumer; 50 51 import java.util.Arrays; 52 53 /** 54 * Satellite modem interface to manage connections with the satellite service and HAL interface. 55 */ 56 public class SatelliteModemInterface { 57 private static final String TAG = "SatelliteModemInterface"; 58 private static final long REBIND_INITIAL_DELAY = 2 * 1000; // 2 seconds 59 private static final long REBIND_MAXIMUM_DELAY = 64 * 1000; // 1 minute 60 private static final int REBIND_MULTIPLIER = 2; 61 62 @NonNull private static SatelliteModemInterface sInstance; 63 @NonNull private final Context mContext; 64 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 65 @NonNull protected final ExponentialBackoff mExponentialBackoff; 66 @NonNull private final Object mLock = new Object(); 67 @NonNull private final SatelliteController mSatelliteController; 68 /** 69 * {@code true} to use the vendor satellite service and {@code false} to use the HAL. 70 */ 71 private boolean mIsSatelliteServiceSupported; 72 @Nullable private ISatellite mSatelliteService; 73 @Nullable private SatelliteServiceConnection mSatelliteServiceConnection; 74 @NonNull private String mVendorSatellitePackageName = ""; 75 private boolean mIsBound; 76 private boolean mIsBinding; 77 78 @NonNull private final RegistrantList mSatelliteProvisionStateChangedRegistrants = 79 new RegistrantList(); 80 @NonNull private final RegistrantList mSatellitePositionInfoChangedRegistrants = 81 new RegistrantList(); 82 @NonNull private final RegistrantList mDatagramTransferStateChangedRegistrants = 83 new RegistrantList(); 84 @NonNull private final RegistrantList mSatelliteModemStateChangedRegistrants = 85 new RegistrantList(); 86 @NonNull private final RegistrantList mPendingDatagramsRegistrants = new RegistrantList(); 87 @NonNull private final RegistrantList mSatelliteDatagramsReceivedRegistrants = 88 new RegistrantList(); 89 90 @NonNull private final ISatelliteListener mListener = new ISatelliteListener.Stub() { 91 @Override 92 public void onSatelliteProvisionStateChanged(boolean provisioned) { 93 mSatelliteProvisionStateChangedRegistrants.notifyResult(provisioned); 94 } 95 96 @Override 97 public void onSatelliteDatagramReceived( 98 android.telephony.satellite.stub.SatelliteDatagram datagram, int pendingCount) { 99 mSatelliteDatagramsReceivedRegistrants.notifyResult(new Pair<>( 100 SatelliteServiceUtils.fromSatelliteDatagram(datagram), pendingCount)); 101 } 102 103 @Override 104 public void onPendingDatagrams() { 105 mPendingDatagramsRegistrants.notifyResult(null); 106 } 107 108 @Override 109 public void onSatellitePositionChanged( 110 android.telephony.satellite.stub.PointingInfo pointingInfo) { 111 mSatellitePositionInfoChangedRegistrants.notifyResult( 112 SatelliteServiceUtils.fromPointingInfo(pointingInfo)); 113 } 114 115 @Override 116 public void onSatelliteModemStateChanged(int state) { 117 mSatelliteModemStateChangedRegistrants.notifyResult( 118 SatelliteServiceUtils.fromSatelliteModemState(state)); 119 int datagramTransferState = SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN; 120 switch (state) { 121 case SatelliteManager.SATELLITE_MODEM_STATE_IDLE: 122 datagramTransferState = SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE; 123 break; 124 case SatelliteManager.SATELLITE_MODEM_STATE_LISTENING: 125 datagramTransferState = 126 SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING; 127 break; 128 case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING: 129 datagramTransferState = 130 SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING; 131 break; 132 case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING: 133 // keep previous state as this could be retrying sending or receiving 134 break; 135 } 136 mDatagramTransferStateChangedRegistrants.notifyResult(datagramTransferState); 137 } 138 }; 139 140 /** 141 * @return The singleton instance of SatelliteModemInterface. 142 */ getInstance()143 public static SatelliteModemInterface getInstance() { 144 if (sInstance == null) { 145 loge("SatelliteModemInterface was not yet initialized."); 146 } 147 return sInstance; 148 } 149 150 /** 151 * Create the SatelliteModemInterface singleton instance. 152 * @param context The Context to use to create the SatelliteModemInterface. 153 * @param satelliteController The singleton instance of SatelliteController. 154 * @return The singleton instance of SatelliteModemInterface. 155 */ make(@onNull Context context, SatelliteController satelliteController)156 public static SatelliteModemInterface make(@NonNull Context context, 157 SatelliteController satelliteController) { 158 if (sInstance == null) { 159 sInstance = new SatelliteModemInterface( 160 context, satelliteController, Looper.getMainLooper()); 161 } 162 return sInstance; 163 } 164 165 /** 166 * Create a SatelliteModemInterface to manage connections to the SatelliteService. 167 * 168 * @param context The Context for the SatelliteModemInterface. 169 * @param looper The Looper to run binding retry on. 170 */ 171 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) SatelliteModemInterface(@onNull Context context, SatelliteController satelliteController, @NonNull Looper looper)172 protected SatelliteModemInterface(@NonNull Context context, 173 SatelliteController satelliteController, @NonNull Looper looper) { 174 mContext = context; 175 mIsSatelliteServiceSupported = getSatelliteServiceSupport(); 176 mSatelliteController = satelliteController; 177 mExponentialBackoff = new ExponentialBackoff(REBIND_INITIAL_DELAY, REBIND_MAXIMUM_DELAY, 178 REBIND_MULTIPLIER, looper, () -> { 179 synchronized (mLock) { 180 if ((mIsBound && mSatelliteService != null) || mIsBinding) { 181 return; 182 } 183 } 184 if (mSatelliteServiceConnection != null) { 185 synchronized (mLock) { 186 mIsBound = false; 187 mIsBinding = false; 188 } 189 unbindService(); 190 } 191 bindService(); 192 }); 193 mExponentialBackoff.start(); 194 logd("Created SatelliteModemInterface. Attempting to bind to SatelliteService."); 195 bindService(); 196 } 197 198 /** 199 * Get the SatelliteService interface, if it exists. 200 * 201 * @return The bound ISatellite, or {@code null} if it is not yet connected. 202 */ getService()203 @Nullable public ISatellite getService() { 204 return mSatelliteService; 205 } 206 getSatellitePackageName()207 @NonNull private String getSatellitePackageName() { 208 if (!TextUtils.isEmpty(mVendorSatellitePackageName)) { 209 return mVendorSatellitePackageName; 210 } 211 return TextUtils.emptyIfNull(mContext.getResources().getString( 212 R.string.config_satellite_service_package)); 213 } 214 getSatelliteServiceSupport()215 private boolean getSatelliteServiceSupport() { 216 return !TextUtils.isEmpty(getSatellitePackageName()); 217 } 218 219 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) bindService()220 protected void bindService() { 221 synchronized (mLock) { 222 if (mIsBinding || mIsBound) return; 223 mIsBinding = true; 224 } 225 String packageName = getSatellitePackageName(); 226 if (TextUtils.isEmpty(packageName)) { 227 loge("Unable to bind to the satellite service because the package is undefined."); 228 // Since the package name comes from static device configs, stop retry because 229 // rebind will continue to fail without a valid package name. 230 synchronized (mLock) { 231 mIsBinding = false; 232 } 233 mExponentialBackoff.stop(); 234 return; 235 } 236 Intent intent = new Intent(SatelliteService.SERVICE_INTERFACE); 237 intent.setPackage(packageName); 238 239 mSatelliteServiceConnection = new SatelliteServiceConnection(); 240 logd("Binding to " + packageName); 241 try { 242 boolean success = mContext.bindService( 243 intent, mSatelliteServiceConnection, Context.BIND_AUTO_CREATE); 244 if (success) { 245 logd("Successfully bound to the satellite service."); 246 } else { 247 synchronized (mLock) { 248 mIsBinding = false; 249 } 250 mExponentialBackoff.notifyFailed(); 251 loge("Error binding to the satellite service. Retrying in " 252 + mExponentialBackoff.getCurrentDelay() + " ms."); 253 } 254 } catch (Exception e) { 255 synchronized (mLock) { 256 mIsBinding = false; 257 } 258 mExponentialBackoff.notifyFailed(); 259 loge("Exception binding to the satellite service. Retrying in " 260 + mExponentialBackoff.getCurrentDelay() + " ms. Exception: " + e); 261 } 262 } 263 264 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) unbindService()265 protected void unbindService() { 266 disconnectSatelliteService(); 267 mContext.unbindService(mSatelliteServiceConnection); 268 mSatelliteServiceConnection = null; 269 } 270 disconnectSatelliteService()271 private void disconnectSatelliteService() { 272 // TODO: clean up any listeners and return failed for pending callbacks 273 mSatelliteService = null; 274 } 275 276 private class SatelliteServiceConnection implements ServiceConnection { 277 @Override onServiceConnected(ComponentName name, IBinder service)278 public void onServiceConnected(ComponentName name, IBinder service) { 279 logd("onServiceConnected: ComponentName=" + name); 280 synchronized (mLock) { 281 mIsBound = true; 282 mIsBinding = false; 283 } 284 mSatelliteService = ISatellite.Stub.asInterface(service); 285 mExponentialBackoff.stop(); 286 try { 287 mSatelliteService.setSatelliteListener(mListener); 288 } catch (RemoteException e) { 289 // TODO: Retry setSatelliteListener 290 logd("setSatelliteListener: RemoteException " + e); 291 } 292 mSatelliteController.onSatelliteServiceConnected(); 293 } 294 295 @Override onServiceDisconnected(ComponentName name)296 public void onServiceDisconnected(ComponentName name) { 297 loge("onServiceDisconnected: Waiting for reconnect."); 298 synchronized (mLock) { 299 mIsBinding = false; 300 } 301 // Since we are still technically bound, clear the service and wait for reconnect. 302 disconnectSatelliteService(); 303 } 304 305 @Override onBindingDied(ComponentName name)306 public void onBindingDied(ComponentName name) { 307 loge("onBindingDied: Unbinding and rebinding service."); 308 synchronized (mLock) { 309 mIsBound = false; 310 mIsBinding = false; 311 } 312 unbindService(); 313 mExponentialBackoff.start(); 314 } 315 } 316 317 /** 318 * Registers for the satellite provision state changed. 319 * 320 * @param h Handler for notification message. 321 * @param what User-defined message code. 322 * @param obj User object. 323 */ registerForSatelliteProvisionStateChanged( @onNull Handler h, int what, @Nullable Object obj)324 public void registerForSatelliteProvisionStateChanged( 325 @NonNull Handler h, int what, @Nullable Object obj) { 326 mSatelliteProvisionStateChangedRegistrants.add(h, what, obj); 327 } 328 329 /** 330 * Unregisters for the satellite provision state changed. 331 * 332 * @param h Handler to be removed from the registrant list. 333 */ unregisterForSatelliteProvisionStateChanged(@onNull Handler h)334 public void unregisterForSatelliteProvisionStateChanged(@NonNull Handler h) { 335 mSatelliteProvisionStateChangedRegistrants.remove(h); 336 } 337 338 /** 339 * Registers for satellite position info changed from satellite modem. 340 * 341 * @param h Handler for notification message. 342 * @param what User-defined message code. 343 * @param obj User object. 344 */ registerForSatellitePositionInfoChanged( @onNull Handler h, int what, @Nullable Object obj)345 public void registerForSatellitePositionInfoChanged( 346 @NonNull Handler h, int what, @Nullable Object obj) { 347 mSatellitePositionInfoChangedRegistrants.add(h, what, obj); 348 } 349 350 /** 351 * Unregisters for satellite position info changed from satellite modem. 352 * 353 * @param h Handler to be removed from the registrant list. 354 */ unregisterForSatellitePositionInfoChanged(@onNull Handler h)355 public void unregisterForSatellitePositionInfoChanged(@NonNull Handler h) { 356 mSatellitePositionInfoChangedRegistrants.remove(h); 357 } 358 359 /** 360 * Registers for datagram transfer state changed. 361 * 362 * @param h Handler for notification message. 363 * @param what User-defined message code. 364 * @param obj User object. 365 */ registerForDatagramTransferStateChanged( @onNull Handler h, int what, @Nullable Object obj)366 public void registerForDatagramTransferStateChanged( 367 @NonNull Handler h, int what, @Nullable Object obj) { 368 mDatagramTransferStateChangedRegistrants.add(h, what, obj); 369 } 370 371 /** 372 * Unregisters for datagram transfer state changed. 373 * 374 * @param h Handler to be removed from the registrant list. 375 */ unregisterForDatagramTransferStateChanged(@onNull Handler h)376 public void unregisterForDatagramTransferStateChanged(@NonNull Handler h) { 377 mDatagramTransferStateChangedRegistrants.remove(h); 378 } 379 380 /** 381 * Registers for modem state changed from satellite modem. 382 * 383 * @param h Handler for notification message. 384 * @param what User-defined message code. 385 * @param obj User object. 386 */ registerForSatelliteModemStateChanged( @onNull Handler h, int what, @Nullable Object obj)387 public void registerForSatelliteModemStateChanged( 388 @NonNull Handler h, int what, @Nullable Object obj) { 389 mSatelliteModemStateChangedRegistrants.add(h, what, obj); 390 } 391 392 /** 393 * Unregisters for modem state changed from satellite modem. 394 * 395 * @param h Handler to be removed from the registrant list. 396 */ unregisterForSatelliteModemStateChanged(@onNull Handler h)397 public void unregisterForSatelliteModemStateChanged(@NonNull Handler h) { 398 mSatelliteModemStateChangedRegistrants.remove(h); 399 } 400 401 /** 402 * Registers for pending datagrams indication from satellite modem. 403 * 404 * @param h Handler for notification message. 405 * @param what User-defined message code. 406 * @param obj User object. 407 */ registerForPendingDatagrams(@onNull Handler h, int what, @Nullable Object obj)408 public void registerForPendingDatagrams(@NonNull Handler h, int what, @Nullable Object obj) { 409 mPendingDatagramsRegistrants.add(h, what, obj); 410 } 411 412 /** 413 * Unregisters for pending datagrams indication from satellite modem. 414 * 415 * @param h Handler to be removed from the registrant list. 416 */ unregisterForPendingDatagrams(@onNull Handler h)417 public void unregisterForPendingDatagrams(@NonNull Handler h) { 418 mPendingDatagramsRegistrants.remove(h); 419 } 420 421 /** 422 * Registers for new datagrams received from satellite modem. 423 * 424 * @param h Handler for notification message. 425 * @param what User-defined message code. 426 * @param obj User object. 427 */ registerForSatelliteDatagramsReceived( @onNull Handler h, int what, @Nullable Object obj)428 public void registerForSatelliteDatagramsReceived( 429 @NonNull Handler h, int what, @Nullable Object obj) { 430 mSatelliteDatagramsReceivedRegistrants.add(h, what, obj); 431 } 432 433 /** 434 * Unregisters for new datagrams received from satellite modem. 435 * 436 * @param h Handler to be removed from the registrant list. 437 */ unregisterForSatelliteDatagramsReceived(@onNull Handler h)438 public void unregisterForSatelliteDatagramsReceived(@NonNull Handler h) { 439 mSatelliteDatagramsReceivedRegistrants.remove(h); 440 } 441 442 /** 443 * Request to enable or disable the satellite service listening mode. 444 * Listening mode allows the satellite service to listen for incoming pages. 445 * 446 * @param enable True to enable satellite listening mode and false to disable. 447 * @param timeout How long the satellite modem should wait for the next incoming page before 448 * disabling listening mode. 449 * @param message The Message to send to result of the operation to. 450 */ requestSatelliteListeningEnabled(boolean enable, int timeout, @Nullable Message message)451 public void requestSatelliteListeningEnabled(boolean enable, int timeout, 452 @Nullable Message message) { 453 if (mSatelliteService != null) { 454 try { 455 mSatelliteService.requestSatelliteListeningEnabled(enable, timeout, 456 new IIntegerConsumer.Stub() { 457 @Override 458 public void accept(int result) { 459 int error = SatelliteServiceUtils.fromSatelliteError(result); 460 logd("requestSatelliteListeningEnabled: " + error); 461 Binder.withCleanCallingIdentity(() -> { 462 if (message != null) { 463 sendMessageWithResult(message, null, error); 464 } 465 }); 466 } 467 }); 468 } catch (RemoteException e) { 469 loge("requestSatelliteListeningEnabled: RemoteException " + e); 470 if (message != null) { 471 sendMessageWithResult( 472 message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 473 } 474 } 475 } else { 476 loge("requestSatelliteListeningEnabled: Satellite service is unavailable."); 477 if (message != null) { 478 sendMessageWithResult(message, null, 479 SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 480 } 481 } 482 } 483 484 /** 485 * Allow cellular modem scanning while satellite mode is on. 486 * @param enabled {@code true} to enable cellular modem while satellite mode is on 487 * and {@code false} to disable 488 * @param message The Message to send to result of the operation to. 489 */ enableCellularModemWhileSatelliteModeIsOn(boolean enabled, @Nullable Message message)490 public void enableCellularModemWhileSatelliteModeIsOn(boolean enabled, 491 @Nullable Message message) { 492 if (mSatelliteService != null) { 493 try { 494 mSatelliteService.enableCellularModemWhileSatelliteModeIsOn(enabled, 495 new IIntegerConsumer.Stub() { 496 @Override 497 public void accept(int result) { 498 int error = SatelliteServiceUtils.fromSatelliteError(result); 499 logd("enableCellularModemWhileSatelliteModeIsOn: " + error); 500 Binder.withCleanCallingIdentity(() -> { 501 if (message != null) { 502 sendMessageWithResult(message, null, error); 503 } 504 }); 505 } 506 }); 507 } catch (RemoteException e) { 508 loge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e); 509 if (message != null) { 510 sendMessageWithResult( 511 message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 512 } 513 } 514 } else { 515 loge("enableCellularModemWhileSatelliteModeIsOn: Satellite service is unavailable."); 516 if (message != null) { 517 sendMessageWithResult(message, null, 518 SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 519 } 520 } 521 } 522 /** 523 * Request to enable or disable the satellite modem and demo mode. If the satellite modem 524 * is enabled, this may also disable the cellular modem, and if the satellite modem is disabled, 525 * this may also re-enable the cellular modem. 526 * 527 * @param enableSatellite True to enable the satellite modem and false to disable. 528 * @param enableDemoMode True to enable demo mode and false to disable. 529 * @param message The Message to send to result of the operation to. 530 */ requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode, @NonNull Message message)531 public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode, 532 @NonNull Message message) { 533 if (mSatelliteService != null) { 534 try { 535 mSatelliteService.requestSatelliteEnabled(enableSatellite, enableDemoMode, 536 new IIntegerConsumer.Stub() { 537 @Override 538 public void accept(int result) { 539 int error = SatelliteServiceUtils.fromSatelliteError(result); 540 logd("setSatelliteEnabled: " + error); 541 Binder.withCleanCallingIdentity(() -> 542 sendMessageWithResult(message, null, error)); 543 } 544 }); 545 } catch (RemoteException e) { 546 loge("setSatelliteEnabled: RemoteException " + e); 547 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 548 } 549 } else { 550 loge("setSatelliteEnabled: Satellite service is unavailable."); 551 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 552 } 553 } 554 555 /** 556 * Request to get whether the satellite modem is enabled. 557 * 558 * @param message The Message to send to result of the operation to. 559 */ requestIsSatelliteEnabled(@onNull Message message)560 public void requestIsSatelliteEnabled(@NonNull Message message) { 561 if (mSatelliteService != null) { 562 try { 563 mSatelliteService.requestIsSatelliteEnabled(new IIntegerConsumer.Stub() { 564 @Override 565 public void accept(int result) { 566 int error = SatelliteServiceUtils.fromSatelliteError(result); 567 logd("requestIsSatelliteEnabled: " + error); 568 Binder.withCleanCallingIdentity(() -> 569 sendMessageWithResult(message, null, error)); 570 } 571 }, new IBooleanConsumer.Stub() { 572 @Override 573 public void accept(boolean result) { 574 // Convert for compatibility with SatelliteResponse 575 // TODO: This should just report result instead. 576 int[] enabled = new int[] {result ? 1 : 0}; 577 logd("requestIsSatelliteEnabled: " + Arrays.toString(enabled)); 578 Binder.withCleanCallingIdentity(() -> sendMessageWithResult( 579 message, enabled, SatelliteManager.SATELLITE_ERROR_NONE)); 580 } 581 }); 582 } catch (RemoteException e) { 583 loge("requestIsSatelliteEnabled: RemoteException " + e); 584 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 585 } 586 } else { 587 loge("requestIsSatelliteEnabled: Satellite service is unavailable."); 588 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 589 } 590 } 591 592 /** 593 * Request to get whether the satellite service is supported on the device. 594 * 595 * @param message The Message to send to result of the operation to. 596 */ requestIsSatelliteSupported(@onNull Message message)597 public void requestIsSatelliteSupported(@NonNull Message message) { 598 if (mSatelliteService != null) { 599 try { 600 mSatelliteService.requestIsSatelliteSupported(new IIntegerConsumer.Stub() { 601 @Override 602 public void accept(int result) { 603 int error = SatelliteServiceUtils.fromSatelliteError(result); 604 logd("requestIsSatelliteSupported: " + error); 605 Binder.withCleanCallingIdentity(() -> 606 sendMessageWithResult(message, null, error)); 607 } 608 }, new IBooleanConsumer.Stub() { 609 @Override 610 public void accept(boolean result) { 611 logd("requestIsSatelliteSupported: " + result); 612 Binder.withCleanCallingIdentity(() -> sendMessageWithResult( 613 message, result, SatelliteManager.SATELLITE_ERROR_NONE)); 614 } 615 }); 616 } catch (RemoteException e) { 617 loge("requestIsSatelliteSupported: RemoteException " + e); 618 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 619 } 620 } else { 621 loge("requestIsSatelliteSupported: Satellite service is unavailable."); 622 sendMessageWithResult( 623 message, null, SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 624 } 625 } 626 627 /** 628 * Request to get the SatelliteCapabilities of the satellite service. 629 * 630 * @param message The Message to send to result of the operation to. 631 */ requestSatelliteCapabilities(@onNull Message message)632 public void requestSatelliteCapabilities(@NonNull Message message) { 633 if (mSatelliteService != null) { 634 try { 635 mSatelliteService.requestSatelliteCapabilities(new IIntegerConsumer.Stub() { 636 @Override 637 public void accept(int result) { 638 int error = SatelliteServiceUtils.fromSatelliteError(result); 639 logd("requestSatelliteCapabilities: " + error); 640 Binder.withCleanCallingIdentity(() -> 641 sendMessageWithResult(message, null, error)); 642 } 643 }, new ISatelliteCapabilitiesConsumer.Stub() { 644 @Override 645 public void accept(android.telephony.satellite.stub.SatelliteCapabilities 646 result) { 647 SatelliteCapabilities capabilities = 648 SatelliteServiceUtils.fromSatelliteCapabilities(result); 649 logd("requestSatelliteCapabilities: " + capabilities); 650 Binder.withCleanCallingIdentity(() -> sendMessageWithResult( 651 message, capabilities, SatelliteManager.SATELLITE_ERROR_NONE)); 652 } 653 }); 654 } catch (RemoteException e) { 655 loge("requestSatelliteCapabilities: RemoteException " + e); 656 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 657 } 658 } else { 659 loge("requestSatelliteCapabilities: Satellite service is unavailable."); 660 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 661 } 662 } 663 664 /** 665 * User started pointing to the satellite. 666 * The satellite service should report the satellite pointing info via 667 * ISatelliteListener#onSatellitePositionChanged as the user device/satellite moves. 668 * 669 * @param message The Message to send to result of the operation to. 670 */ startSendingSatellitePointingInfo(@onNull Message message)671 public void startSendingSatellitePointingInfo(@NonNull Message message) { 672 if (mSatelliteService != null) { 673 try { 674 mSatelliteService.startSendingSatellitePointingInfo(new IIntegerConsumer.Stub() { 675 @Override 676 public void accept(int result) { 677 int error = SatelliteServiceUtils.fromSatelliteError(result); 678 logd("startSendingSatellitePointingInfo: " + error); 679 Binder.withCleanCallingIdentity(() -> 680 sendMessageWithResult(message, null, error)); 681 } 682 }); 683 } catch (RemoteException e) { 684 loge("startSendingSatellitePointingInfo: RemoteException " + e); 685 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 686 } 687 } else { 688 loge("startSendingSatellitePointingInfo: Satellite service is unavailable."); 689 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 690 } 691 } 692 693 /** 694 * User stopped pointing to the satellite. 695 * The satellite service should stop reporting satellite pointing info to the framework. 696 * 697 * @param message The Message to send to result of the operation to. 698 */ stopSendingSatellitePointingInfo(@onNull Message message)699 public void stopSendingSatellitePointingInfo(@NonNull Message message) { 700 if (mSatelliteService != null) { 701 try { 702 mSatelliteService.stopSendingSatellitePointingInfo(new IIntegerConsumer.Stub() { 703 @Override 704 public void accept(int result) { 705 int error = SatelliteServiceUtils.fromSatelliteError(result); 706 logd("stopSendingSatellitePointingInfo: " + error); 707 Binder.withCleanCallingIdentity(() -> 708 sendMessageWithResult(message, null, error)); 709 } 710 }); 711 } catch (RemoteException e) { 712 loge("stopSendingSatellitePointingInfo: RemoteException " + e); 713 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 714 } 715 } else { 716 loge("stopSendingSatellitePointingInfo: Satellite service is unavailable."); 717 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 718 } 719 } 720 721 /** 722 * Provision the device with a satellite provider. 723 * This is needed if the provider allows dynamic registration. 724 * Once provisioned, ISatelliteListener#onSatelliteProvisionStateChanged should report true. 725 * 726 * @param token The token to be used as a unique identifier for provisioning with satellite 727 * gateway. 728 * @param provisionData Data from the provisioning app that can be used by provisioning server 729 * @param message The Message to send to result of the operation to. 730 */ provisionSatelliteService(@onNull String token, @NonNull byte[] provisionData, @NonNull Message message)731 public void provisionSatelliteService(@NonNull String token, @NonNull byte[] provisionData, 732 @NonNull Message message) { 733 if (mSatelliteService != null) { 734 try { 735 mSatelliteService.provisionSatelliteService(token, provisionData, 736 new IIntegerConsumer.Stub() { 737 @Override 738 public void accept(int result) { 739 int error = SatelliteServiceUtils.fromSatelliteError(result); 740 logd("provisionSatelliteService: " + error); 741 Binder.withCleanCallingIdentity(() -> 742 sendMessageWithResult(message, null, error)); 743 } 744 }); 745 } catch (RemoteException e) { 746 loge("provisionSatelliteService: RemoteException " + e); 747 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 748 } 749 } else { 750 loge("provisionSatelliteService: Satellite service is unavailable."); 751 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 752 } 753 } 754 755 /** 756 * Deprovision the device with the satellite provider. 757 * This is needed if the provider allows dynamic registration. 758 * Once deprovisioned, ISatelliteListener#onSatelliteProvisionStateChanged should report false. 759 * 760 * @param token The token of the device/subscription to be deprovisioned. 761 * @param message The Message to send to result of the operation to. 762 */ deprovisionSatelliteService(@onNull String token, @NonNull Message message)763 public void deprovisionSatelliteService(@NonNull String token, @NonNull Message message) { 764 if (mSatelliteService != null) { 765 try { 766 mSatelliteService.deprovisionSatelliteService(token, new IIntegerConsumer.Stub() { 767 @Override 768 public void accept(int result) { 769 int error = SatelliteServiceUtils.fromSatelliteError(result); 770 logd("deprovisionSatelliteService: " + error); 771 Binder.withCleanCallingIdentity(() -> 772 sendMessageWithResult(message, null, error)); 773 } 774 }); 775 } catch (RemoteException e) { 776 loge("deprovisionSatelliteService: RemoteException " + e); 777 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 778 } 779 } else { 780 loge("deprovisionSatelliteService: Satellite service is unavailable."); 781 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 782 } 783 } 784 785 /** 786 * Request to get whether this device is provisioned with a satellite provider. 787 * 788 * @param message The Message to send to result of the operation to. 789 */ requestIsSatelliteProvisioned(@onNull Message message)790 public void requestIsSatelliteProvisioned(@NonNull Message message) { 791 if (mSatelliteService != null) { 792 try { 793 mSatelliteService.requestIsSatelliteProvisioned(new IIntegerConsumer.Stub() { 794 @Override 795 public void accept(int result) { 796 int error = SatelliteServiceUtils.fromSatelliteError(result); 797 logd("requestIsSatelliteProvisioned: " + error); 798 Binder.withCleanCallingIdentity(() -> 799 sendMessageWithResult(message, null, error)); 800 } 801 }, new IBooleanConsumer.Stub() { 802 @Override 803 public void accept(boolean result) { 804 // Convert for compatibility with SatelliteResponse 805 // TODO: This should just report result instead. 806 int[] provisioned = new int[] {result ? 1 : 0}; 807 logd("requestIsSatelliteProvisioned: " + Arrays.toString(provisioned)); 808 Binder.withCleanCallingIdentity(() -> sendMessageWithResult( 809 message, provisioned, SatelliteManager.SATELLITE_ERROR_NONE)); 810 } 811 }); 812 } catch (RemoteException e) { 813 loge("requestIsSatelliteProvisioned: RemoteException " + e); 814 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 815 } 816 } else { 817 loge("requestIsSatelliteProvisioned: Satellite service is unavailable."); 818 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 819 } 820 } 821 822 /** 823 * Poll the pending datagrams to be received over satellite. 824 * The satellite service should check if there are any pending datagrams to be received over 825 * satellite and report them via ISatelliteListener#onSatelliteDatagramsReceived. 826 * 827 * @param message The Message to send to result of the operation to. 828 */ pollPendingSatelliteDatagrams(@onNull Message message)829 public void pollPendingSatelliteDatagrams(@NonNull Message message) { 830 if (mSatelliteService != null) { 831 try { 832 mSatelliteService.pollPendingSatelliteDatagrams(new IIntegerConsumer.Stub() { 833 @Override 834 public void accept(int result) { 835 int error = SatelliteServiceUtils.fromSatelliteError(result); 836 logd("pollPendingSatelliteDatagrams: " + error); 837 Binder.withCleanCallingIdentity(() -> 838 sendMessageWithResult(message, null, error)); 839 } 840 }); 841 } catch (RemoteException e) { 842 loge("pollPendingSatelliteDatagrams: RemoteException " + e); 843 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 844 } 845 } else { 846 loge("pollPendingSatelliteDatagrams: Satellite service is unavailable."); 847 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 848 } 849 } 850 851 /** 852 * Send datagram over satellite. 853 * 854 * @param datagram Datagram to send in byte format. 855 * @param isEmergency Whether this is an emergency datagram. 856 * @param needFullScreenPointingUI this is used to indicate pointingUI app to open in 857 * full screen mode. 858 * @param message The Message to send to result of the operation to. 859 */ sendSatelliteDatagram(@onNull SatelliteDatagram datagram, boolean isEmergency, boolean needFullScreenPointingUI, @NonNull Message message)860 public void sendSatelliteDatagram(@NonNull SatelliteDatagram datagram, boolean isEmergency, 861 boolean needFullScreenPointingUI, @NonNull Message message) { 862 if (mSatelliteService != null) { 863 try { 864 mSatelliteService.sendSatelliteDatagram( 865 SatelliteServiceUtils.toSatelliteDatagram(datagram), isEmergency, 866 new IIntegerConsumer.Stub() { 867 @Override 868 public void accept(int result) { 869 int error = SatelliteServiceUtils.fromSatelliteError(result); 870 logd("sendSatelliteDatagram: " + error); 871 Binder.withCleanCallingIdentity(() -> 872 sendMessageWithResult(message, null, error)); 873 } 874 }); 875 } catch (RemoteException e) { 876 loge("sendSatelliteDatagram: RemoteException " + e); 877 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 878 } 879 } else { 880 loge("sendSatelliteDatagram: Satellite service is unavailable."); 881 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 882 } 883 } 884 885 /** 886 * Request the current satellite modem state. 887 * The satellite service should report the current satellite modem state via 888 * ISatelliteListener#onSatelliteModemStateChanged. 889 * 890 * @param message The Message to send to result of the operation to. 891 */ requestSatelliteModemState(@onNull Message message)892 public void requestSatelliteModemState(@NonNull Message message) { 893 if (mSatelliteService != null) { 894 try { 895 mSatelliteService.requestSatelliteModemState(new IIntegerConsumer.Stub() { 896 @Override 897 public void accept(int result) { 898 int error = SatelliteServiceUtils.fromSatelliteError(result); 899 logd("requestSatelliteModemState: " + error); 900 Binder.withCleanCallingIdentity(() -> 901 sendMessageWithResult(message, null, error)); 902 } 903 }, new IIntegerConsumer.Stub() { 904 @Override 905 public void accept(int result) { 906 // Convert SatelliteModemState from service to frameworks definition. 907 int modemState = SatelliteServiceUtils.fromSatelliteModemState(result); 908 logd("requestSatelliteModemState: " + modemState); 909 Binder.withCleanCallingIdentity(() -> sendMessageWithResult( 910 message, modemState, SatelliteManager.SATELLITE_ERROR_NONE)); 911 } 912 }); 913 } catch (RemoteException e) { 914 loge("requestSatelliteModemState: RemoteException " + e); 915 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 916 } 917 } else { 918 loge("requestSatelliteModemState: Satellite service is unavailable."); 919 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 920 } 921 } 922 923 /** 924 * Request to get whether satellite communication is allowed for the current location. 925 * 926 * @param message The Message to send to result of the operation to. 927 */ requestIsSatelliteCommunicationAllowedForCurrentLocation(@onNull Message message)928 public void requestIsSatelliteCommunicationAllowedForCurrentLocation(@NonNull Message message) { 929 if (mSatelliteService != null) { 930 try { 931 mSatelliteService.requestIsSatelliteCommunicationAllowedForCurrentLocation( 932 new IIntegerConsumer.Stub() { 933 @Override 934 public void accept(int result) { 935 int error = SatelliteServiceUtils.fromSatelliteError(result); 936 logd("requestIsSatelliteCommunicationAllowedForCurrentLocation: " 937 + error); 938 Binder.withCleanCallingIdentity(() -> 939 sendMessageWithResult(message, null, error)); 940 } 941 }, new IBooleanConsumer.Stub() { 942 @Override 943 public void accept(boolean result) { 944 logd("requestIsSatelliteCommunicationAllowedForCurrentLocation: " 945 + result); 946 Binder.withCleanCallingIdentity(() -> sendMessageWithResult( 947 message, result, SatelliteManager.SATELLITE_ERROR_NONE)); 948 } 949 }); 950 } catch (RemoteException e) { 951 loge("requestIsSatelliteCommunicationAllowedForCurrentLocation: RemoteException " 952 + e); 953 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 954 } 955 } else { 956 loge("requestIsSatelliteCommunicationAllowedForCurrentLocation: " 957 + "Satellite service is unavailable."); 958 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 959 } 960 } 961 962 /** 963 * Request to get the time after which the satellite will be visible. This is an int 964 * representing the duration in seconds after which the satellite will be visible. 965 * This will return 0 if the satellite is currently visible. 966 * 967 * @param message The Message to send to result of the operation to. 968 */ requestTimeForNextSatelliteVisibility(@onNull Message message)969 public void requestTimeForNextSatelliteVisibility(@NonNull Message message) { 970 if (mSatelliteService != null) { 971 try { 972 mSatelliteService.requestTimeForNextSatelliteVisibility( 973 new IIntegerConsumer.Stub() { 974 @Override 975 public void accept(int result) { 976 int error = SatelliteServiceUtils.fromSatelliteError(result); 977 logd("requestTimeForNextSatelliteVisibility: " + error); 978 Binder.withCleanCallingIdentity(() -> 979 sendMessageWithResult(message, null, error)); 980 } 981 }, new IIntegerConsumer.Stub() { 982 @Override 983 public void accept(int result) { 984 // Convert for compatibility with SatelliteResponse 985 // TODO: This should just report result instead. 986 int[] time = new int[] {result}; 987 logd("requestTimeForNextSatelliteVisibility: " 988 + Arrays.toString(time)); 989 Binder.withCleanCallingIdentity(() -> sendMessageWithResult( 990 message, time, SatelliteManager.SATELLITE_ERROR_NONE)); 991 } 992 }); 993 } catch (RemoteException e) { 994 loge("requestTimeForNextSatelliteVisibility: RemoteException " + e); 995 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_SERVICE_ERROR); 996 } 997 } else { 998 loge("requestTimeForNextSatelliteVisibility: Satellite service is unavailable."); 999 sendMessageWithResult(message, null, SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE); 1000 } 1001 } 1002 isSatelliteServiceSupported()1003 public boolean isSatelliteServiceSupported() { 1004 return mIsSatelliteServiceSupported; 1005 } 1006 1007 /** 1008 * This API can be used by only CTS to update satellite vendor service package name. 1009 * 1010 * @param servicePackageName The package name of the satellite vendor service. 1011 * @return {@code true} if the satellite vendor service is set successfully, 1012 * {@code false} otherwise. 1013 */ 1014 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) setSatelliteServicePackageName(@ullable String servicePackageName)1015 public void setSatelliteServicePackageName(@Nullable String servicePackageName) { 1016 logd("setSatelliteServicePackageName: config_satellite_service_package is " 1017 + "updated, new packageName=" + servicePackageName); 1018 mExponentialBackoff.stop(); 1019 if (mSatelliteServiceConnection != null) { 1020 synchronized (mLock) { 1021 mIsBound = false; 1022 mIsBinding = false; 1023 } 1024 unbindService(); 1025 } 1026 1027 if (servicePackageName == null || servicePackageName.equals("null")) { 1028 mVendorSatellitePackageName = ""; 1029 } else { 1030 mVendorSatellitePackageName = servicePackageName; 1031 } 1032 mIsSatelliteServiceSupported = getSatelliteServiceSupport(); 1033 bindService(); 1034 mExponentialBackoff.start(); 1035 } 1036 1037 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) sendMessageWithResult(@onNull Message message, @Nullable Object result, @SatelliteManager.SatelliteError int error)1038 protected static void sendMessageWithResult(@NonNull Message message, @Nullable Object result, 1039 @SatelliteManager.SatelliteError int error) { 1040 SatelliteException exception = error == SatelliteManager.SATELLITE_ERROR_NONE 1041 ? null : new SatelliteException(error); 1042 AsyncResult.forMessage(message, result, exception); 1043 message.sendToTarget(); 1044 } 1045 logd(@onNull String log)1046 private static void logd(@NonNull String log) { 1047 Rlog.d(TAG, log); 1048 } 1049 loge(@onNull String log)1050 private static void loge(@NonNull String log) { 1051 Rlog.e(TAG, log); 1052 } 1053 } 1054