1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.telephony.satellite; 18 19 import android.Manifest; 20 import android.annotation.CallbackExecutor; 21 import android.annotation.FlaggedApi; 22 import android.annotation.Hide; 23 import android.annotation.IntDef; 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.annotation.RequiresFeature; 27 import android.annotation.RequiresPermission; 28 import android.annotation.SystemApi; 29 import android.annotation.SystemService; 30 import android.content.Context; 31 import android.content.pm.PackageManager; 32 import android.os.Binder; 33 import android.os.Bundle; 34 import android.os.CancellationSignal; 35 import android.os.ICancellationSignal; 36 import android.os.OutcomeReceiver; 37 import android.os.RemoteException; 38 import android.os.ResultReceiver; 39 import android.telephony.CarrierConfigManager; 40 import android.telephony.SubscriptionManager; 41 import android.telephony.TelephonyCallback; 42 import android.telephony.TelephonyFrameworkInitializer; 43 import android.telephony.TelephonyManager; 44 import android.telephony.TelephonyRegistryManager; 45 46 import com.android.internal.telephony.IBooleanConsumer; 47 import com.android.internal.telephony.IIntegerConsumer; 48 import com.android.internal.telephony.ITelephony; 49 import com.android.internal.telephony.IVoidConsumer; 50 import com.android.internal.telephony.flags.Flags; 51 import com.android.telephony.Rlog; 52 53 import java.lang.annotation.Retention; 54 import java.lang.annotation.RetentionPolicy; 55 import java.time.Duration; 56 import java.util.ArrayList; 57 import java.util.Arrays; 58 import java.util.HashSet; 59 import java.util.List; 60 import java.util.Objects; 61 import java.util.Set; 62 import java.util.concurrent.ConcurrentHashMap; 63 import java.util.concurrent.Executor; 64 import java.util.function.Consumer; 65 import java.util.stream.Collectors; 66 67 /** 68 * Manages satellite states such as monitoring enabled state and operations such as provisioning, 69 * pointing, messaging, location sharing, etc. 70 * 71 * <p>To get the object, call {@link Context#getSystemService(String)} with 72 * {@link Context#SATELLITE_SERVICE}. 73 * 74 * <p>SatelliteManager is intended for use on devices with feature 75 * {@link PackageManager#FEATURE_TELEPHONY_SATELLITE}. On devices without the feature, the behavior 76 * is not reliable. 77 */ 78 @SystemService(Context.SATELLITE_SERVICE) 79 @FlaggedApi(Flags.FLAG_SATELLITE_STATE_CHANGE_LISTENER) 80 @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SATELLITE) 81 public final class SatelliteManager { 82 private static final String TAG = "SatelliteManager"; 83 84 private static final ConcurrentHashMap<SatelliteDatagramCallback, ISatelliteDatagramCallback> 85 sSatelliteDatagramCallbackMap = new ConcurrentHashMap<>(); 86 private static final ConcurrentHashMap<SatelliteProvisionStateCallback, 87 ISatelliteProvisionStateCallback> sSatelliteProvisionStateCallbackMap = 88 new ConcurrentHashMap<>(); 89 private static final ConcurrentHashMap<SatelliteModemStateCallback, 90 ISatelliteModemStateCallback> 91 sSatelliteModemStateCallbackMap = new ConcurrentHashMap<>(); 92 private static final ConcurrentHashMap<SatelliteTransmissionUpdateCallback, 93 ISatelliteTransmissionUpdateCallback> sSatelliteTransmissionUpdateCallbackMap = 94 new ConcurrentHashMap<>(); 95 private static final ConcurrentHashMap<NtnSignalStrengthCallback, INtnSignalStrengthCallback> 96 sNtnSignalStrengthCallbackMap = new ConcurrentHashMap<>(); 97 private static final ConcurrentHashMap<SatelliteCapabilitiesCallback, 98 ISatelliteCapabilitiesCallback> 99 sSatelliteCapabilitiesCallbackMap = new ConcurrentHashMap<>(); 100 private static final ConcurrentHashMap<Consumer<Boolean>, 101 IBooleanConsumer> sSatelliteSupportedStateCallbackMap = 102 new ConcurrentHashMap<>(); 103 private static final ConcurrentHashMap<SatelliteCommunicationAccessStateCallback, 104 ISatelliteCommunicationAccessStateCallback> 105 sSatelliteCommunicationAccessStateCallbackMap = 106 new ConcurrentHashMap<>(); 107 private static final ConcurrentHashMap<SatelliteDisallowedReasonsCallback, 108 ISatelliteDisallowedReasonsCallback> 109 sSatelliteDisallowedReasonsCallbackMap = 110 new ConcurrentHashMap<>(); 111 private static final ConcurrentHashMap<SelectedNbIotSatelliteSubscriptionCallback, 112 ISelectedNbIotSatelliteSubscriptionCallback> 113 sSelectedNbIotSatelliteSubscriptionCallbackMap = 114 new ConcurrentHashMap<>(); 115 116 private final int mSubId; 117 118 /** 119 * Context this SatelliteManager is for. 120 */ 121 @Nullable private final Context mContext; 122 123 private TelephonyRegistryManager mTelephonyRegistryMgr; 124 125 /** 126 * Create an instance of the SatelliteManager. 127 * 128 * @param context The context the SatelliteManager belongs to. 129 * @hide 130 */ SatelliteManager(@ullable Context context)131 public SatelliteManager(@Nullable Context context) { 132 this(context, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 133 } 134 135 /** 136 * Create an instance of the SatelliteManager associated with a particular subscription. 137 * 138 * @param context The context the SatelliteManager belongs to. 139 * @param subId The subscription ID associated with the SatelliteManager. 140 */ SatelliteManager(@ullable Context context, int subId)141 private SatelliteManager(@Nullable Context context, int subId) { 142 mContext = context; 143 mSubId = subId; 144 } 145 146 /** 147 * Exception from the satellite service containing the {@link SatelliteResult} error code. 148 * @hide 149 */ 150 @SystemApi 151 public static class SatelliteException extends Exception { 152 @SatelliteResult private final int mErrorCode; 153 154 /** 155 * Create a SatelliteException with a given error code. 156 * 157 * @param errorCode The {@link SatelliteResult}. 158 */ SatelliteException(@atelliteResult int errorCode)159 public SatelliteException(@SatelliteResult int errorCode) { 160 mErrorCode = errorCode; 161 } 162 163 /** 164 * Get the error code returned from the satellite service. 165 * 166 * @return The {@link SatelliteResult}. 167 */ getErrorCode()168 @SatelliteResult public int getErrorCode() { 169 return mErrorCode; 170 } 171 } 172 173 /** 174 * Bundle key to get the response from 175 * {@link #requestIsEnabled(Executor, OutcomeReceiver)}. 176 * @hide 177 */ 178 179 public static final String KEY_SATELLITE_ENABLED = "satellite_enabled"; 180 181 /** 182 * Bundle key to get the response from 183 * {@link #requestIsDemoModeEnabled(Executor, OutcomeReceiver)}. 184 * @hide 185 */ 186 187 public static final String KEY_DEMO_MODE_ENABLED = "demo_mode_enabled"; 188 189 /** 190 * Bundle key to get the response from 191 * {@link #requestIsEmergencyModeEnabled(Executor, OutcomeReceiver)}. 192 * @hide 193 */ 194 public static final String KEY_EMERGENCY_MODE_ENABLED = "emergency_mode_enabled"; 195 196 /** 197 * Bundle key to get the response from 198 * {@link #requestIsSupported(Executor, OutcomeReceiver)}. 199 * @hide 200 */ 201 202 public static final String KEY_SATELLITE_SUPPORTED = "satellite_supported"; 203 204 /** 205 * Bundle key to get the response from 206 * {@link #requestCapabilities(Executor, OutcomeReceiver)}. 207 * @hide 208 */ 209 210 public static final String KEY_SATELLITE_CAPABILITIES = "satellite_capabilities"; 211 212 /** 213 * Bundle key to get the response from 214 * {@link #requestSessionStats(Executor, OutcomeReceiver)}. 215 * @hide 216 */ 217 218 public static final String KEY_SESSION_STATS = "session_stats"; 219 220 /** 221 * Bundle key to get the response from 222 * {@link #requestSessionStats(Executor, OutcomeReceiver)}. 223 * @hide 224 */ 225 226 public static final String KEY_SESSION_STATS_V2 = "session_stats_v2"; 227 228 /** 229 * Bundle key to get the response from 230 * {@link #requestIsProvisioned(Executor, OutcomeReceiver)}. 231 * @hide 232 */ 233 234 public static final String KEY_SATELLITE_PROVISIONED = "satellite_provisioned"; 235 236 /** 237 * Bundle key to get the response from 238 * {@link #requestIsCommunicationAllowedForCurrentLocation(Executor, OutcomeReceiver)}. 239 * @hide 240 */ 241 242 public static final String KEY_SATELLITE_COMMUNICATION_ALLOWED = 243 "satellite_communication_allowed"; 244 245 /** 246 * Bundle key to get the response from 247 * {@link #requestTimeForNextSatelliteVisibility(Executor, OutcomeReceiver)}. 248 * @hide 249 */ 250 251 public static final String KEY_SATELLITE_NEXT_VISIBILITY = "satellite_next_visibility"; 252 253 /** 254 * Bundle key to get the response from 255 * {@link #requestNtnSignalStrength(Executor, OutcomeReceiver)}. 256 * @hide 257 */ 258 259 public static final String KEY_NTN_SIGNAL_STRENGTH = "ntn_signal_strength"; 260 261 /** 262 * Bundle key to get the response from 263 * {@link #requestSatelliteSubscriberProvisionStatus(Executor, OutcomeReceiver)}. 264 * @hide 265 */ 266 public static final String KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN = 267 "request_provision_subscriber_id"; 268 269 /** 270 * Bundle key to get the response from 271 * {@link #provisionSatellite(List, Executor, OutcomeReceiver)}. 272 * @hide 273 */ 274 public static final String KEY_PROVISION_SATELLITE_TOKENS = "provision_satellite"; 275 276 /** 277 * Bundle key to get the response from 278 * {@link #deprovisionSatellite(List, Executor, OutcomeReceiver)}. 279 * @hide 280 */ 281 public static final String KEY_DEPROVISION_SATELLITE_TOKENS = "deprovision_satellite"; 282 283 /** 284 * Bundle key to get the response from 285 * {@link #requestSatelliteAccessConfigurationForCurrentLocation(Executor, OutcomeReceiver)}. 286 * @hide 287 */ 288 public static final String KEY_SATELLITE_ACCESS_CONFIGURATION = 289 "satellite_access_configuration"; 290 291 /** 292 * Bundle key to get the response from 293 * {@link #requestSatelliteDisplayName(Executor, OutcomeReceiver)}. 294 * @hide 295 */ 296 public static final String KEY_SATELLITE_DISPLAY_NAME = "satellite_display_name"; 297 298 /** 299 * Bundle key to get the response from 300 * {@link #requestSelectedNbIotSatelliteSubscriptionId(Executor, OutcomeReceiver)}. 301 * @hide 302 */ 303 public static final String KEY_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_ID = 304 "selected_nb_iot_satellite_subscription_id"; 305 306 /** 307 * The request was successfully processed. 308 * @hide 309 */ 310 @SystemApi 311 public static final int SATELLITE_RESULT_SUCCESS = 0; 312 313 /** 314 * A generic error which should be used only when other specific errors cannot be used. 315 * @hide 316 */ 317 @SystemApi 318 public static final int SATELLITE_RESULT_ERROR = 1; 319 320 /** 321 * Error received from the satellite server. 322 * @hide 323 */ 324 @SystemApi 325 public static final int SATELLITE_RESULT_SERVER_ERROR = 2; 326 327 /** 328 * Error received from the vendor service. This generic error code should be used 329 * only when the error cannot be mapped to other specific service error codes. 330 * @hide 331 */ 332 @SystemApi 333 public static final int SATELLITE_RESULT_SERVICE_ERROR = 3; 334 335 /** 336 * Error received from satellite modem. This generic error code should be used only when 337 * the error cannot be mapped to other specific modem error codes. 338 * @hide 339 */ 340 @SystemApi 341 public static final int SATELLITE_RESULT_MODEM_ERROR = 4; 342 343 /** 344 * Error received from the satellite network. This generic error code should be used only when 345 * the error cannot be mapped to other specific network error codes. 346 * @hide 347 */ 348 @SystemApi 349 public static final int SATELLITE_RESULT_NETWORK_ERROR = 5; 350 351 /** 352 * Telephony is not in a valid state to receive requests from clients. 353 * @hide 354 */ 355 @SystemApi 356 public static final int SATELLITE_RESULT_INVALID_TELEPHONY_STATE = 6; 357 358 /** 359 * Satellite modem is not in a valid state to receive requests from clients. 360 * @hide 361 */ 362 @SystemApi 363 public static final int SATELLITE_RESULT_INVALID_MODEM_STATE = 7; 364 365 /** 366 * Either vendor service, or modem, or Telephony framework has received a request with 367 * invalid arguments from its clients. 368 * @hide 369 */ 370 @SystemApi 371 public static final int SATELLITE_RESULT_INVALID_ARGUMENTS = 8; 372 373 /** 374 * Telephony framework failed to send a request or receive a response from the vendor service 375 * or satellite modem due to internal error. 376 * @hide 377 */ 378 @SystemApi 379 public static final int SATELLITE_RESULT_REQUEST_FAILED = 9; 380 381 /** 382 * Radio did not start or is resetting. 383 * @hide 384 */ 385 @SystemApi 386 public static final int SATELLITE_RESULT_RADIO_NOT_AVAILABLE = 10; 387 388 /** 389 * The request is not supported by either the satellite modem or the network. 390 * @hide 391 */ 392 @SystemApi 393 public static final int SATELLITE_RESULT_REQUEST_NOT_SUPPORTED = 11; 394 395 /** 396 * Satellite modem or network has no resources available to handle requests from clients. 397 * @hide 398 */ 399 @SystemApi 400 public static final int SATELLITE_RESULT_NO_RESOURCES = 12; 401 402 /** 403 * Satellite service is not provisioned yet. 404 * @hide 405 */ 406 @SystemApi 407 public static final int SATELLITE_RESULT_SERVICE_NOT_PROVISIONED = 13; 408 409 /** 410 * Satellite service provision is already in progress. 411 * @hide 412 */ 413 @SystemApi 414 public static final int SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS = 14; 415 416 /** 417 * The ongoing request was aborted by either the satellite modem or the network. 418 * This error is also returned when framework decides to abort current send request as one 419 * of the previous send request failed. 420 * @hide 421 */ 422 @SystemApi 423 public static final int SATELLITE_RESULT_REQUEST_ABORTED = 15; 424 425 /** 426 * The device/subscriber is barred from accessing the satellite service. 427 * @hide 428 */ 429 @SystemApi 430 public static final int SATELLITE_RESULT_ACCESS_BARRED = 16; 431 432 /** 433 * Satellite modem timeout to receive ACK or response from the satellite network after 434 * sending a request to the network. 435 * @hide 436 */ 437 @SystemApi 438 public static final int SATELLITE_RESULT_NETWORK_TIMEOUT = 17; 439 440 /** 441 * Satellite network is not reachable from the modem. 442 * @hide 443 */ 444 @SystemApi 445 public static final int SATELLITE_RESULT_NOT_REACHABLE = 18; 446 447 /** 448 * The device/subscriber is not authorized to register with the satellite service provider. 449 * @hide 450 */ 451 @SystemApi 452 public static final int SATELLITE_RESULT_NOT_AUTHORIZED = 19; 453 454 /** 455 * The device does not support satellite. 456 * @hide 457 */ 458 @SystemApi 459 public static final int SATELLITE_RESULT_NOT_SUPPORTED = 20; 460 461 /** 462 * The current request is already in-progress. 463 * @hide 464 */ 465 @SystemApi 466 public static final int SATELLITE_RESULT_REQUEST_IN_PROGRESS = 21; 467 468 /** 469 * Satellite modem is currently busy due to which current request cannot be processed. 470 * @hide 471 */ 472 @SystemApi 473 public static final int SATELLITE_RESULT_MODEM_BUSY = 22; 474 475 /** 476 * Telephony process is not currently available or satellite is not supported. 477 * @hide 478 */ 479 @SystemApi 480 public static final int SATELLITE_RESULT_ILLEGAL_STATE = 23; 481 482 /** 483 * Telephony framework timeout to receive ACK or response from the satellite modem after 484 * sending a request to the modem. 485 * @hide 486 */ 487 @SystemApi 488 public static final int SATELLITE_RESULT_MODEM_TIMEOUT = 24; 489 490 /** 491 * Telephony framework needs to access the current location of the device to perform the 492 * request. However, location in the settings is disabled by users. 493 * @hide 494 */ 495 @SystemApi 496 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 497 public static final int SATELLITE_RESULT_LOCATION_DISABLED = 25; 498 499 /** 500 * Telephony framework needs to access the current location of the device to perform the 501 * request. However, Telephony fails to fetch the current location from location service. 502 * @hide 503 */ 504 @SystemApi 505 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 506 public static final int SATELLITE_RESULT_LOCATION_NOT_AVAILABLE = 26; 507 508 /** 509 * Emergency call is in progress. 510 * @hide 511 */ 512 @SystemApi 513 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 514 public static final int SATELLITE_RESULT_EMERGENCY_CALL_IN_PROGRESS = 27; 515 516 /** 517 * Disabling satellite is in progress. 518 * @hide 519 */ 520 @SystemApi 521 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 522 public static final int SATELLITE_RESULT_DISABLE_IN_PROGRESS = 28; 523 524 /** 525 * Enabling satellite is in progress. 526 * @hide 527 */ 528 @SystemApi 529 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 530 public static final int SATELLITE_RESULT_ENABLE_IN_PROGRESS = 29; 531 532 /** 533 * There is no valid satellite subscription selected. 534 * @hide 535 */ 536 @SystemApi 537 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 538 public static final int SATELLITE_RESULT_NO_VALID_SATELLITE_SUBSCRIPTION = 30; 539 540 /** @hide */ 541 @IntDef(prefix = {"SATELLITE_RESULT_"}, value = { 542 SATELLITE_RESULT_SUCCESS, 543 SATELLITE_RESULT_ERROR, 544 SATELLITE_RESULT_SERVER_ERROR, 545 SATELLITE_RESULT_SERVICE_ERROR, 546 SATELLITE_RESULT_MODEM_ERROR, 547 SATELLITE_RESULT_NETWORK_ERROR, 548 SATELLITE_RESULT_INVALID_TELEPHONY_STATE, 549 SATELLITE_RESULT_INVALID_MODEM_STATE, 550 SATELLITE_RESULT_INVALID_ARGUMENTS, 551 SATELLITE_RESULT_REQUEST_FAILED, 552 SATELLITE_RESULT_RADIO_NOT_AVAILABLE, 553 SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, 554 SATELLITE_RESULT_NO_RESOURCES, 555 SATELLITE_RESULT_SERVICE_NOT_PROVISIONED, 556 SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS, 557 SATELLITE_RESULT_REQUEST_ABORTED, 558 SATELLITE_RESULT_ACCESS_BARRED, 559 SATELLITE_RESULT_NETWORK_TIMEOUT, 560 SATELLITE_RESULT_NOT_REACHABLE, 561 SATELLITE_RESULT_NOT_AUTHORIZED, 562 SATELLITE_RESULT_NOT_SUPPORTED, 563 SATELLITE_RESULT_REQUEST_IN_PROGRESS, 564 SATELLITE_RESULT_MODEM_BUSY, 565 SATELLITE_RESULT_ILLEGAL_STATE, 566 SATELLITE_RESULT_MODEM_TIMEOUT, 567 SATELLITE_RESULT_LOCATION_DISABLED, 568 SATELLITE_RESULT_LOCATION_NOT_AVAILABLE, 569 SATELLITE_RESULT_EMERGENCY_CALL_IN_PROGRESS, 570 SATELLITE_RESULT_DISABLE_IN_PROGRESS, 571 SATELLITE_RESULT_ENABLE_IN_PROGRESS, 572 SATELLITE_RESULT_NO_VALID_SATELLITE_SUBSCRIPTION 573 }) 574 @Retention(RetentionPolicy.SOURCE) 575 public @interface SatelliteResult {} 576 577 /** 578 * Unknown Non-Terrestrial radio technology. This generic radio technology should be used 579 * only when the radio technology cannot be mapped to other specific radio technologies. 580 * @hide 581 */ 582 @SystemApi 583 public static final int NT_RADIO_TECHNOLOGY_UNKNOWN = 0; 584 585 /** 586 * 3GPP NB-IoT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology. 587 * @hide 588 */ 589 @SystemApi 590 public static final int NT_RADIO_TECHNOLOGY_NB_IOT_NTN = 1; 591 592 /** 593 * 3GPP 5G NR over Non-Terrestrial-Networks technology. 594 * @hide 595 */ 596 @SystemApi 597 public static final int NT_RADIO_TECHNOLOGY_NR_NTN = 2; 598 599 /** 600 * 3GPP eMTC (enhanced Machine-Type Communication) over Non-Terrestrial-Networks technology. 601 * @hide 602 */ 603 @SystemApi 604 public static final int NT_RADIO_TECHNOLOGY_EMTC_NTN = 3; 605 606 /** 607 * Proprietary technology. 608 * @hide 609 */ 610 @SystemApi 611 public static final int NT_RADIO_TECHNOLOGY_PROPRIETARY = 4; 612 613 /** @hide */ 614 @IntDef(prefix = "NT_RADIO_TECHNOLOGY_", value = { 615 NT_RADIO_TECHNOLOGY_UNKNOWN, 616 NT_RADIO_TECHNOLOGY_NB_IOT_NTN, 617 NT_RADIO_TECHNOLOGY_NR_NTN, 618 NT_RADIO_TECHNOLOGY_EMTC_NTN, 619 NT_RADIO_TECHNOLOGY_PROPRIETARY 620 }) 621 @Retention(RetentionPolicy.SOURCE) 622 public @interface NTRadioTechnology {} 623 624 /** 625 * Suggested device hold position is unknown. 626 * @hide 627 */ 628 @SystemApi 629 public static final int DEVICE_HOLD_POSITION_UNKNOWN = 0; 630 631 /** 632 * User is suggested to hold the device in portrait mode. 633 * @hide 634 */ 635 @SystemApi 636 public static final int DEVICE_HOLD_POSITION_PORTRAIT = 1; 637 638 /** 639 * User is suggested to hold the device in landscape mode with left hand. 640 * @hide 641 */ 642 @SystemApi 643 public static final int DEVICE_HOLD_POSITION_LANDSCAPE_LEFT = 2; 644 645 /** 646 * User is suggested to hold the device in landscape mode with right hand. 647 * @hide 648 */ 649 @SystemApi 650 public static final int DEVICE_HOLD_POSITION_LANDSCAPE_RIGHT = 3; 651 652 /** @hide */ 653 @IntDef(prefix = {"DEVICE_HOLD_POSITION_"}, value = { 654 DEVICE_HOLD_POSITION_UNKNOWN, 655 DEVICE_HOLD_POSITION_PORTRAIT, 656 DEVICE_HOLD_POSITION_LANDSCAPE_LEFT, 657 DEVICE_HOLD_POSITION_LANDSCAPE_RIGHT 658 }) 659 @Retention(RetentionPolicy.SOURCE) 660 public @interface DeviceHoldPosition {} 661 662 /** 663 * Display mode is unknown. 664 * @hide 665 */ 666 @SystemApi 667 public static final int DISPLAY_MODE_UNKNOWN = 0; 668 669 /** 670 * Display mode of the device used for satellite communication for non-foldable phones. 671 * @hide 672 */ 673 @SystemApi 674 public static final int DISPLAY_MODE_FIXED = 1; 675 676 /** 677 * Display mode of the device used for satellite communication for foldabale phones when the 678 * device is opened. 679 * @hide 680 */ 681 @SystemApi 682 public static final int DISPLAY_MODE_OPENED = 2; 683 684 /** 685 * Display mode of the device used for satellite communication for foldabable phones when the 686 * device is closed. 687 * @hide 688 */ 689 @SystemApi 690 public static final int DISPLAY_MODE_CLOSED = 3; 691 692 /** @hide */ 693 @IntDef(prefix = {"ANTENNA_POSITION_"}, value = { 694 DISPLAY_MODE_UNKNOWN, 695 DISPLAY_MODE_FIXED, 696 DISPLAY_MODE_OPENED, 697 DISPLAY_MODE_CLOSED 698 }) 699 @Retention(RetentionPolicy.SOURCE) 700 public @interface DisplayMode {} 701 702 /** 703 * Unknown or unsupported value for data mode on satellite. 704 * @hide 705 */ 706 @SystemApi 707 @FlaggedApi(Flags.FLAG_SATELLITE_25Q4_APIS) 708 public static final int SATELLITE_DATA_SUPPORT_UNKNOWN = -1; 709 710 /** 711 * Support only restricted data usecases like carrier messaging using RCS. 712 * @hide 713 */ 714 @SystemApi 715 @FlaggedApi(Flags.FLAG_SATELLITE_25Q4_APIS) 716 public static final int SATELLITE_DATA_SUPPORT_RESTRICTED = 0; 717 718 /** 719 * Support constrained internet which would enable internet only for applications that are 720 * modified. 721 * 722 * <p> 723 * To get internet access, applications need to be modified to use the satellite data 724 * optimized network. This can be done by setting the {@link #PROPERTY_SATELLITE_DATA_OPTIMIZED} 725 * property to {@code true} in the manifest. 726 * </p> 727 * 728 * @hide 729 */ 730 @SystemApi 731 @FlaggedApi(Flags.FLAG_SATELLITE_25Q4_APIS) 732 public static final int SATELLITE_DATA_SUPPORT_CONSTRAINED = 1; 733 734 /** 735 * Support default internet on satellite without any restrictions on any apps. 736 * @hide 737 */ 738 @SystemApi 739 @FlaggedApi(Flags.FLAG_SATELLITE_25Q4_APIS) 740 public static final int SATELLITE_DATA_SUPPORT_UNCONSTRAINED = 2; 741 742 /** @hide */ 743 @IntDef(prefix = {"SATELLITE_DATA_SUPPORT_"}, value = { 744 SATELLITE_DATA_SUPPORT_UNKNOWN, 745 SATELLITE_DATA_SUPPORT_RESTRICTED, 746 SATELLITE_DATA_SUPPORT_CONSTRAINED, 747 SATELLITE_DATA_SUPPORT_UNCONSTRAINED, 748 }) 749 @Retention(RetentionPolicy.SOURCE) 750 public @interface SatelliteDataSupportMode {} 751 752 /** 753 * The emergency call is handed over to oem-enabled satellite SOS messaging. SOS messages are 754 * sent to SOS providers, which will then forward the messages to emergency providers. 755 * @hide 756 */ 757 @SystemApi 758 public static final int EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS = 1; 759 760 /** 761 * The emergency call is handed over to carrier-enabled satellite T911 messaging. T911 messages 762 * are sent directly to local emergency providers. 763 * @hide 764 */ 765 @SystemApi 766 public static final int EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911 = 2; 767 768 /** 769 * This intent will be broadcasted if there are any change to list of subscriber information. 770 * This intent will be sent only to the app with component defined in 771 * config_satellite_carrier_roaming_esos_provisioned_class and package defined in 772 * config_satellite_gateway_service_package 773 * @hide 774 */ 775 @SystemApi 776 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 777 public static final String ACTION_SATELLITE_SUBSCRIBER_ID_LIST_CHANGED = 778 "android.telephony.satellite.action.SATELLITE_SUBSCRIBER_ID_LIST_CHANGED"; 779 780 781 /** 782 * This intent will be broadcasted to start a non-emergency session. 783 * This intent will be sent only to the app with component defined in 784 * config_satellite_carrier_roaming_non_emergency_session_class and package defined in 785 * config_satellite_gateway_service_package 786 * @hide 787 */ 788 @SystemApi 789 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 790 public static final String ACTION_SATELLITE_START_NON_EMERGENCY_SESSION = 791 "android.telephony.satellite.action.SATELLITE_START_NON_EMERGENCY_SESSION"; 792 793 /** 794 * Application level {@link android.content.pm.PackageManager.Property} tag that represents 795 * whether the application supports P2P SMS over carrier roaming satellite which needs manual 796 * trigger to connect to satellite. The messaging applications that supports P2P SMS over 797 * carrier roaming satellite should set value of this property to {@code true}. 798 * 799 * <p><b>Syntax:</b> 800 * <pre> 801 * <application> 802 * <property 803 * android:name="android.telephony.satellite.PROPERTY_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT" 804 * android:value="true"/> 805 * </application> 806 * </pre> 807 * @hide 808 */ 809 @SystemApi 810 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 811 public static final String PROPERTY_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT = 812 "android.telephony.satellite.PROPERTY_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT"; 813 814 /** 815 * Meta-data represents whether the application supports P2P SMS over carrier roaming satellite 816 * which needs manual trigger to connect to satellite. The messaging applications that supports 817 * P2P SMS over carrier roaming satellites should add the following in their AndroidManifest. 818 * {@code 819 * <application 820 * <meta-data 821 * android:name="android.telephony.METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT" 822 * android:value="true"/> 823 * </application> 824 * } 825 * @hide 826 */ 827 public static final String METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT = 828 "android.telephony.METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT"; 829 830 /** 831 * A boolean value indicating whether application is optimized to utilize low bandwidth 832 * satellite data. 833 * The applications that are optimized for low bandwidth satellite data should set this 834 * property to {@code true} in the manifest to indicate to platform about the same. 835 * {@code 836 * <application> 837 * <meta-data 838 * android:name="android.telephony.PROPERTY_SATELLITE_DATA_OPTIMIZED" 839 * android:value="true"/> 840 * </application> 841 * } 842 * <p> 843 * When {@code true}, satellite data optimized network is available for applications. 844 */ 845 @FlaggedApi(Flags.FLAG_SATELLITE_25Q4_APIS) 846 public static final String PROPERTY_SATELLITE_DATA_OPTIMIZED = 847 "android.telephony.PROPERTY_SATELLITE_DATA_OPTIMIZED"; 848 849 /** 850 * Registers a {@link SatelliteStateChangeListener} to receive callbacks when the satellite 851 * state may have changed. 852 * 853 * <p>The callback method is immediately triggered with latest state on invoking this method if 854 * the state change has been notified before. 855 * 856 * @param executor The {@link Executor} where the {@code listener} will be invoked 857 * @param listener The listener to monitor the satellite state change 858 * 859 * @see SatelliteStateChangeListener 860 * @see TelephonyManager#hasCarrierPrivileges() 861 */ 862 @FlaggedApi(Flags.FLAG_SATELLITE_STATE_CHANGE_LISTENER) 863 @RequiresPermission(anyOf = {android.Manifest.permission.READ_BASIC_PHONE_STATE, 864 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 865 android.Manifest.permission.READ_PHONE_STATE, 866 "carrier privileges"}) registerStateChangeListener(@onNull @allbackExecutor Executor executor, @NonNull SatelliteStateChangeListener listener)867 public void registerStateChangeListener(@NonNull @CallbackExecutor Executor executor, 868 @NonNull SatelliteStateChangeListener listener) { 869 if (mContext == null) { 870 throw new IllegalStateException("Telephony service is null"); 871 } 872 873 mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class); 874 if (mTelephonyRegistryMgr == null) { 875 throw new IllegalStateException("Telephony registry service is null"); 876 } 877 mTelephonyRegistryMgr.addSatelliteStateChangeListener(executor, listener); 878 } 879 880 /** 881 * Unregisters the {@link SatelliteStateChangeListener} previously registered with 882 * {@link #registerStateChangeListener(Executor, SatelliteStateChangeListener)}. 883 * 884 * <p>It will be a no-op if the {@code listener} is not currently registered. 885 * 886 * @param listener The listener to unregister 887 * 888 * @see SatelliteStateChangeListener 889 * @see TelephonyManager#hasCarrierPrivileges() 890 */ 891 @FlaggedApi(Flags.FLAG_SATELLITE_STATE_CHANGE_LISTENER) 892 @RequiresPermission(anyOf = {android.Manifest.permission.READ_BASIC_PHONE_STATE, 893 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 894 android.Manifest.permission.READ_PHONE_STATE, 895 "carrier privileges"}) unregisterStateChangeListener(@onNull SatelliteStateChangeListener listener)896 public void unregisterStateChangeListener(@NonNull SatelliteStateChangeListener listener) { 897 if (mContext == null) { 898 throw new IllegalStateException("Telephony service is null"); 899 } 900 901 mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class); 902 if (mTelephonyRegistryMgr == null) { 903 throw new IllegalStateException("Telephony registry service is null"); 904 } 905 mTelephonyRegistryMgr.removeSatelliteStateChangeListener(listener); 906 } 907 908 /** 909 * Request to enable or disable the satellite modem and demo mode. 910 * If satellite modem and cellular modem cannot work concurrently, 911 * then this will disable the cellular modem if satellite modem is enabled, 912 * and will re-enable the cellular modem if satellite modem is disabled. 913 * 914 * Demo mode is created to simulate the experience of sending and receiving messages over 915 * satellite. If user enters demo mode, a request should be sent to framework to enable 916 * satellite with enableDemoMode set to {code true}. Once satellite is enabled and device is 917 * aligned with the satellite, user can send a message and also receive a reply in demo mode. 918 * If enableSatellite is {@code false}, enableDemoMode has no impact on the behavior. 919 * 920 * @param attributes The attributes of the enable request. 921 * @param executor The executor on which the error code listener will be called. 922 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 923 * 924 * @throws SecurityException if the caller doesn't have required permission. 925 * 926 * @hide 927 */ 928 @SystemApi 929 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) requestEnabled(@onNull EnableRequestAttributes attributes, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)930 public void requestEnabled(@NonNull EnableRequestAttributes attributes, 931 @NonNull @CallbackExecutor Executor executor, 932 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 933 Objects.requireNonNull(attributes); 934 Objects.requireNonNull(executor); 935 Objects.requireNonNull(resultListener); 936 937 try { 938 ITelephony telephony = getITelephony(); 939 if (telephony != null) { 940 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 941 @Override 942 public void accept(int result) { 943 executor.execute(() -> Binder.withCleanCallingIdentity( 944 () -> resultListener.accept(result))); 945 } 946 }; 947 telephony.requestSatelliteEnabled(attributes.isEnabled(), 948 attributes.isDemoMode(), attributes.isEmergencyMode(), errorCallback); 949 } else { 950 Rlog.e(TAG, "requestEnabled() invalid telephony"); 951 executor.execute(() -> Binder.withCleanCallingIdentity( 952 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 953 } 954 } catch (RemoteException ex) { 955 Rlog.e(TAG, "requestEnabled() exception: ", ex); 956 executor.execute(() -> Binder.withCleanCallingIdentity( 957 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 958 } 959 } 960 961 /** 962 * Request to get whether the satellite modem is enabled. 963 * 964 * @param executor The executor on which the callback will be called. 965 * @param callback The callback object to which the result will be delivered. 966 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 967 * will return a {@code boolean} with value {@code true} if the satellite modem 968 * is enabled and {@code false} otherwise. 969 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 970 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 971 * 972 * @throws SecurityException if the caller doesn't have required permission. 973 * 974 * @hide 975 */ 976 @SystemApi 977 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) requestIsEnabled(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteException> callback)978 public void requestIsEnabled(@NonNull @CallbackExecutor Executor executor, 979 @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { 980 Objects.requireNonNull(executor); 981 Objects.requireNonNull(callback); 982 983 try { 984 ITelephony telephony = getITelephony(); 985 if (telephony != null) { 986 ResultReceiver receiver = new ResultReceiver(null) { 987 @Override 988 protected void onReceiveResult(int resultCode, Bundle resultData) { 989 if (resultCode == SATELLITE_RESULT_SUCCESS) { 990 if (resultData.containsKey(KEY_SATELLITE_ENABLED)) { 991 boolean isSatelliteEnabled = 992 resultData.getBoolean(KEY_SATELLITE_ENABLED); 993 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 994 callback.onResult(isSatelliteEnabled))); 995 } else { 996 loge("KEY_SATELLITE_ENABLED does not exist."); 997 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 998 callback.onError(new SatelliteException( 999 SATELLITE_RESULT_REQUEST_FAILED)))); 1000 } 1001 } else { 1002 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1003 callback.onError(new SatelliteException(resultCode)))); 1004 } 1005 } 1006 }; 1007 telephony.requestIsSatelliteEnabled(receiver); 1008 } else { 1009 loge("requestIsEnabled() invalid telephony"); 1010 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 1011 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 1012 } 1013 } catch (RemoteException ex) { 1014 loge("requestIsEnabled() RemoteException: " + ex); 1015 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 1016 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 1017 } 1018 } 1019 1020 /** 1021 * Request to get whether the satellite service demo mode is enabled. 1022 * 1023 * @param executor The executor on which the callback will be called. 1024 * @param callback The callback object to which the result will be delivered. 1025 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 1026 * will return a {@code boolean} with value {@code true} if demo mode is enabled 1027 * and {@code false} otherwise. 1028 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 1029 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 1030 * 1031 * @throws SecurityException if the caller doesn't have required permission. 1032 * 1033 * @hide 1034 */ 1035 @SystemApi 1036 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) requestIsDemoModeEnabled(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteException> callback)1037 public void requestIsDemoModeEnabled(@NonNull @CallbackExecutor Executor executor, 1038 @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { 1039 Objects.requireNonNull(executor); 1040 Objects.requireNonNull(callback); 1041 1042 try { 1043 ITelephony telephony = getITelephony(); 1044 if (telephony != null) { 1045 ResultReceiver receiver = new ResultReceiver(null) { 1046 @Override 1047 protected void onReceiveResult(int resultCode, Bundle resultData) { 1048 if (resultCode == SATELLITE_RESULT_SUCCESS) { 1049 if (resultData.containsKey(KEY_DEMO_MODE_ENABLED)) { 1050 boolean isDemoModeEnabled = 1051 resultData.getBoolean(KEY_DEMO_MODE_ENABLED); 1052 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1053 callback.onResult(isDemoModeEnabled))); 1054 } else { 1055 loge("KEY_DEMO_MODE_ENABLED does not exist."); 1056 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1057 callback.onError(new SatelliteException( 1058 SATELLITE_RESULT_REQUEST_FAILED)))); 1059 } 1060 } else { 1061 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1062 callback.onError(new SatelliteException(resultCode)))); 1063 } 1064 } 1065 }; 1066 telephony.requestIsDemoModeEnabled(receiver); 1067 } else { 1068 loge("requestIsDemoModeEnabled() invalid telephony"); 1069 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 1070 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 1071 } 1072 } catch (RemoteException ex) { 1073 loge("requestIsDemoModeEnabled() RemoteException: " + ex); 1074 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 1075 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 1076 } 1077 } 1078 1079 /** 1080 * Request to get whether the satellite service is enabled for emergency mode. 1081 * 1082 * @param executor The executor on which the callback will be called. 1083 * @param callback The callback object to which the result will be delivered. 1084 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 1085 * will return a {@code boolean} with value {@code true} if satellite is enabled 1086 * for emergency mode and {@code false} otherwise. 1087 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 1088 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 1089 * 1090 * @throws SecurityException if the caller doesn't have required permission. 1091 * 1092 * @hide 1093 */ 1094 @SystemApi 1095 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) requestIsEmergencyModeEnabled(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteException> callback)1096 public void requestIsEmergencyModeEnabled(@NonNull @CallbackExecutor Executor executor, 1097 @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { 1098 Objects.requireNonNull(executor); 1099 Objects.requireNonNull(callback); 1100 1101 try { 1102 ITelephony telephony = getITelephony(); 1103 if (telephony != null) { 1104 ResultReceiver receiver = new ResultReceiver(null) { 1105 @Override 1106 protected void onReceiveResult(int resultCode, Bundle resultData) { 1107 if (resultCode == SATELLITE_RESULT_SUCCESS) { 1108 if (resultData.containsKey(KEY_EMERGENCY_MODE_ENABLED)) { 1109 boolean isEmergencyModeEnabled = 1110 resultData.getBoolean(KEY_EMERGENCY_MODE_ENABLED); 1111 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1112 callback.onResult(isEmergencyModeEnabled))); 1113 } else { 1114 loge("KEY_EMERGENCY_MODE_ENABLED does not exist."); 1115 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1116 callback.onError(new SatelliteException( 1117 SATELLITE_RESULT_REQUEST_FAILED)))); 1118 } 1119 } else { 1120 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1121 callback.onError(new SatelliteException(resultCode)))); 1122 } 1123 } 1124 }; 1125 telephony.requestIsEmergencyModeEnabled(receiver); 1126 } else { 1127 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 1128 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 1129 } 1130 } catch (RemoteException ex) { 1131 loge("requestIsEmergencyModeEnabled() RemoteException: " + ex); 1132 ex.rethrowAsRuntimeException(); 1133 } 1134 } 1135 1136 /** 1137 * Request to get whether the satellite service is supported on the device. 1138 * 1139 * <p> 1140 * Note: This API only checks whether the device supports the satellite feature. The result will 1141 * not be affected by whether the device is provisioned. 1142 * </p> 1143 * 1144 * @param executor The executor on which the callback will be called. 1145 * @param callback The callback object to which the result will be delivered. 1146 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 1147 * will return a {@code boolean} with value {@code true} if the satellite 1148 * service is supported on the device and {@code false} otherwise. 1149 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 1150 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 1151 * 1152 * @hide 1153 */ 1154 @SystemApi requestIsSupported(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteException> callback)1155 public void requestIsSupported(@NonNull @CallbackExecutor Executor executor, 1156 @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { 1157 Objects.requireNonNull(executor); 1158 Objects.requireNonNull(callback); 1159 1160 try { 1161 ITelephony telephony = getITelephony(); 1162 if (telephony != null) { 1163 ResultReceiver receiver = new ResultReceiver(null) { 1164 @Override 1165 protected void onReceiveResult(int resultCode, Bundle resultData) { 1166 if (resultCode == SATELLITE_RESULT_SUCCESS) { 1167 if (resultData.containsKey(KEY_SATELLITE_SUPPORTED)) { 1168 boolean isSatelliteSupported = 1169 resultData.getBoolean(KEY_SATELLITE_SUPPORTED); 1170 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1171 callback.onResult(isSatelliteSupported))); 1172 } else { 1173 loge("KEY_SATELLITE_SUPPORTED does not exist."); 1174 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1175 callback.onError(new SatelliteException( 1176 SATELLITE_RESULT_REQUEST_FAILED)))); 1177 } 1178 } else { 1179 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1180 callback.onError(new SatelliteException(resultCode)))); 1181 } 1182 } 1183 }; 1184 telephony.requestIsSatelliteSupported(receiver); 1185 } else { 1186 loge("requestIsSupported() invalid telephony"); 1187 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 1188 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 1189 } 1190 } catch (RemoteException ex) { 1191 loge("requestIsSupported() RemoteException: " + ex); 1192 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 1193 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 1194 } 1195 } 1196 1197 /** 1198 * Request to get the {@link SatelliteCapabilities} of the satellite service. 1199 * 1200 * @param executor The executor on which the callback will be called. 1201 * @param callback The callback object to which the result will be delivered. 1202 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 1203 * will return the {@link SatelliteCapabilities} of the satellite service. 1204 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 1205 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 1206 * 1207 * @throws SecurityException if the caller doesn't have required permission. 1208 * 1209 * @hide 1210 */ 1211 @SystemApi 1212 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) requestCapabilities(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<SatelliteCapabilities, SatelliteException> callback)1213 public void requestCapabilities(@NonNull @CallbackExecutor Executor executor, 1214 @NonNull OutcomeReceiver<SatelliteCapabilities, SatelliteException> callback) { 1215 Objects.requireNonNull(executor); 1216 Objects.requireNonNull(callback); 1217 1218 try { 1219 ITelephony telephony = getITelephony(); 1220 if (telephony != null) { 1221 ResultReceiver receiver = new ResultReceiver(null) { 1222 @Override 1223 protected void onReceiveResult(int resultCode, Bundle resultData) { 1224 if (resultCode == SATELLITE_RESULT_SUCCESS) { 1225 if (resultData.containsKey(KEY_SATELLITE_CAPABILITIES)) { 1226 SatelliteCapabilities capabilities = 1227 resultData.getParcelable(KEY_SATELLITE_CAPABILITIES, 1228 SatelliteCapabilities.class); 1229 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1230 callback.onResult(capabilities))); 1231 } else { 1232 loge("KEY_SATELLITE_CAPABILITIES does not exist."); 1233 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1234 callback.onError(new SatelliteException( 1235 SATELLITE_RESULT_REQUEST_FAILED)))); 1236 } 1237 } else { 1238 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1239 callback.onError(new SatelliteException(resultCode)))); 1240 } 1241 } 1242 }; 1243 telephony.requestSatelliteCapabilities(receiver); 1244 } else { 1245 loge("requestCapabilities() invalid telephony"); 1246 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 1247 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 1248 } 1249 } catch (RemoteException ex) { 1250 loge("requestCapabilities() RemoteException: " + ex); 1251 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 1252 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 1253 } 1254 } 1255 1256 /** 1257 * The default state indicating that datagram transfer is idle. 1258 * This should be sent if there are no message transfer activity happening. 1259 * @hide 1260 */ 1261 @SystemApi 1262 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE = 0; 1263 1264 /** 1265 * A transition state indicating that a datagram is being sent. 1266 * @hide 1267 */ 1268 @SystemApi 1269 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING = 1; 1270 1271 /** 1272 * An end state indicating that datagram sending completed successfully. 1273 * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE} 1274 * will be sent if no more messages are pending. 1275 * @hide 1276 */ 1277 @SystemApi 1278 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS = 2; 1279 1280 /** 1281 * An end state indicating that datagram sending completed with a failure. 1282 * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE} 1283 * must be sent before reporting any additional datagram transfer state changes. All pending 1284 * messages will be reported as failed, to the corresponding applications. 1285 * @hide 1286 */ 1287 @SystemApi 1288 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED = 3; 1289 1290 /** 1291 * A transition state indicating that a datagram is being received. 1292 * @hide 1293 */ 1294 @SystemApi 1295 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING = 4; 1296 1297 /** 1298 * An end state indicating that datagram receiving completed successfully. 1299 * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE} 1300 * will be sent if no more messages are pending. 1301 * @hide 1302 */ 1303 @SystemApi 1304 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS = 5; 1305 1306 /** 1307 * An end state indicating that datagram receive operation found that there are no 1308 * messages to be retrieved from the satellite. 1309 * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE} 1310 * will be sent if no more messages are pending. 1311 * @hide 1312 */ 1313 @SystemApi 1314 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE = 6; 1315 1316 /** 1317 * An end state indicating that datagram receive completed with a failure. 1318 * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE} 1319 * will be sent if no more messages are pending. 1320 * @hide 1321 */ 1322 @SystemApi 1323 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED = 7; 1324 1325 /** 1326 * A transition state indicating that Telephony is waiting for satellite modem to connect to a 1327 * satellite network before sending a datagram or polling for datagrams. If the satellite modem 1328 * successfully connects to a satellite network, either 1329 * {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING} or 1330 * {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING} will be sent. Otherwise, 1331 * either {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED} or 1332 * {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED} will be sent. 1333 * @hide 1334 */ 1335 @SystemApi 1336 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT = 8; 1337 1338 /** 1339 * The datagram transfer state is unknown. This generic datagram transfer state should be used 1340 * only when the datagram transfer state cannot be mapped to other specific datagram transfer 1341 * states. 1342 * @hide 1343 */ 1344 @SystemApi 1345 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN = -1; 1346 1347 /** @hide */ 1348 @IntDef(prefix = {"SATELLITE_DATAGRAM_TRANSFER_STATE_"}, value = { 1349 SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 1350 SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, 1351 SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS, 1352 SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED, 1353 SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING, 1354 SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS, 1355 SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE, 1356 SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED, 1357 SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT, 1358 SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN 1359 }) 1360 @Retention(RetentionPolicy.SOURCE) 1361 public @interface SatelliteDatagramTransferState {} 1362 // TODO: Split into two enums for sending and receiving states 1363 1364 /** 1365 * Satellite modem is in idle state. 1366 * @hide 1367 */ 1368 @SystemApi 1369 public static final int SATELLITE_MODEM_STATE_IDLE = 0; 1370 1371 /** 1372 * Satellite modem is listening for incoming datagrams. 1373 * @hide 1374 */ 1375 @SystemApi 1376 public static final int SATELLITE_MODEM_STATE_LISTENING = 1; 1377 1378 /** 1379 * Satellite modem is sending and/or receiving datagrams. 1380 * @hide 1381 */ 1382 @SystemApi 1383 public static final int SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING = 2; 1384 1385 /** 1386 * Satellite modem is retrying to send and/or receive datagrams. 1387 * @hide 1388 */ 1389 @SystemApi 1390 public static final int SATELLITE_MODEM_STATE_DATAGRAM_RETRYING = 3; 1391 1392 /** 1393 * Satellite modem is powered off. 1394 * @hide 1395 */ 1396 @SystemApi 1397 public static final int SATELLITE_MODEM_STATE_OFF = 4; 1398 1399 /** 1400 * Satellite modem is unavailable. 1401 * @hide 1402 */ 1403 @SystemApi 1404 public static final int SATELLITE_MODEM_STATE_UNAVAILABLE = 5; 1405 1406 /** 1407 * The satellite modem is powered on but the device is not registered to a satellite cell. 1408 * @hide 1409 */ 1410 @SystemApi 1411 public static final int SATELLITE_MODEM_STATE_NOT_CONNECTED = 6; 1412 1413 /** 1414 * The satellite modem is powered on and the device is registered to a satellite cell. 1415 * @hide 1416 */ 1417 @SystemApi 1418 public static final int SATELLITE_MODEM_STATE_CONNECTED = 7; 1419 1420 /** 1421 * The satellite modem is being powered on. 1422 * @hide 1423 */ 1424 @SystemApi 1425 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 1426 public static final int SATELLITE_MODEM_STATE_ENABLING_SATELLITE = 8; 1427 1428 /** 1429 * The satellite modem is being powered off. 1430 * @hide 1431 */ 1432 @SystemApi 1433 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 1434 public static final int SATELLITE_MODEM_STATE_DISABLING_SATELLITE = 9; 1435 1436 /** 1437 * Satellite modem state is unknown. This generic modem state should be used only when the 1438 * modem state cannot be mapped to other specific modem states. 1439 * @hide 1440 */ 1441 @SystemApi 1442 public static final int SATELLITE_MODEM_STATE_UNKNOWN = -1; 1443 1444 /** @hide */ 1445 @IntDef(prefix = {"SATELLITE_MODEM_STATE_"}, value = { 1446 SATELLITE_MODEM_STATE_IDLE, 1447 SATELLITE_MODEM_STATE_LISTENING, 1448 SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING, 1449 SATELLITE_MODEM_STATE_DATAGRAM_RETRYING, 1450 SATELLITE_MODEM_STATE_OFF, 1451 SATELLITE_MODEM_STATE_UNAVAILABLE, 1452 SATELLITE_MODEM_STATE_NOT_CONNECTED, 1453 SATELLITE_MODEM_STATE_CONNECTED, 1454 SATELLITE_MODEM_STATE_ENABLING_SATELLITE, 1455 SATELLITE_MODEM_STATE_DISABLING_SATELLITE, 1456 SATELLITE_MODEM_STATE_UNKNOWN 1457 }) 1458 @Retention(RetentionPolicy.SOURCE) 1459 public @interface SatelliteModemState {} 1460 1461 /** 1462 * Datagram type is unknown. This generic datagram type should be used only when the 1463 * datagram type cannot be mapped to other specific datagram types. 1464 * @hide 1465 */ 1466 @SystemApi 1467 public static final int DATAGRAM_TYPE_UNKNOWN = 0; 1468 1469 /** 1470 * Datagram type indicating that the datagram to be sent or received is of type SOS message. 1471 * @hide 1472 */ 1473 @SystemApi 1474 public static final int DATAGRAM_TYPE_SOS_MESSAGE = 1; 1475 1476 /** 1477 * Datagram type indicating that the datagram to be sent or received is of type 1478 * location sharing. 1479 * @hide 1480 */ 1481 @SystemApi 1482 public static final int DATAGRAM_TYPE_LOCATION_SHARING = 2; 1483 1484 /** 1485 * This type of datagram is used to keep the device in satellite connected state or check if 1486 * there is any incoming message. 1487 * @hide 1488 */ 1489 @SystemApi 1490 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 1491 public static final int DATAGRAM_TYPE_KEEP_ALIVE = 3; 1492 1493 /** 1494 * Datagram type indicating that the datagram to be sent or received is of type SOS message and 1495 * is the last message to emergency service provider indicating still needs help. 1496 * @hide 1497 */ 1498 @SystemApi 1499 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 1500 public static final int DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP = 4; 1501 1502 /** 1503 * Datagram type indicating that the datagram to be sent or received is of type SOS message and 1504 * is the last message to emergency service provider indicating no more help is needed. 1505 * @hide 1506 */ 1507 @SystemApi 1508 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 1509 public static final int DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED = 5; 1510 1511 /** 1512 * Datagram type indicating that the message to be sent or received is of type SMS. 1513 * @hide 1514 */ 1515 @SystemApi 1516 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 1517 public static final int DATAGRAM_TYPE_SMS = 6; 1518 1519 /** 1520 * Datagram type indicating that the message to be sent is an SMS checking 1521 * for pending incoming SMS. 1522 * @hide 1523 */ 1524 @SystemApi 1525 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 1526 public static final int DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS = 7; 1527 1528 /** @hide */ 1529 @IntDef(prefix = "DATAGRAM_TYPE_", value = { 1530 DATAGRAM_TYPE_UNKNOWN, 1531 DATAGRAM_TYPE_SOS_MESSAGE, 1532 DATAGRAM_TYPE_LOCATION_SHARING, 1533 DATAGRAM_TYPE_KEEP_ALIVE, 1534 DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP, 1535 DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED, 1536 DATAGRAM_TYPE_SMS, 1537 DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS 1538 }) 1539 @Retention(RetentionPolicy.SOURCE) 1540 public @interface DatagramType {} 1541 1542 /** 1543 * Satellite communication restricted by user. 1544 * @hide 1545 */ 1546 @SystemApi 1547 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 1548 public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER = 0; 1549 1550 /** 1551 * Satellite communication restricted by geolocation. This can be 1552 * triggered based upon geofence input provided by carrier to enable or disable satellite. 1553 * @hide 1554 */ 1555 @SystemApi 1556 public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION = 1; 1557 1558 /** 1559 * Satellite communication restricted by entitlement server. This can be triggered based on 1560 * the EntitlementStatus value received from the entitlement server to enable or disable 1561 * satellite. 1562 * @hide 1563 */ 1564 @SystemApi 1565 public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT = 2; 1566 1567 /** @hide */ 1568 @IntDef(prefix = "SATELLITE_COMMUNICATION_RESTRICTION_REASON_", value = { 1569 SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, 1570 SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION, 1571 SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT 1572 }) 1573 @Retention(RetentionPolicy.SOURCE) 1574 public @interface SatelliteCommunicationRestrictionReason {} 1575 1576 /** 1577 * Satellite is disallowed because it is not supported. 1578 * @hide 1579 */ 1580 public static final int SATELLITE_DISALLOWED_REASON_NOT_SUPPORTED = 0; 1581 1582 /** 1583 * Satellite is disallowed because it has not been provisioned. 1584 * @hide 1585 */ 1586 public static final int SATELLITE_DISALLOWED_REASON_NOT_PROVISIONED = 1; 1587 1588 /** 1589 * Satellite is disallowed because it is currently outside an allowed region. 1590 * @hide 1591 */ 1592 public static final int SATELLITE_DISALLOWED_REASON_NOT_IN_ALLOWED_REGION = 2; 1593 1594 /** 1595 * Satellite is disallowed because an unsupported default message application is being used. 1596 * @hide 1597 */ 1598 public static final int SATELLITE_DISALLOWED_REASON_UNSUPPORTED_DEFAULT_MSG_APP = 3; 1599 1600 /** 1601 * Satellite is disallowed because location settings have been disabled. 1602 * @hide 1603 */ 1604 public static final int SATELLITE_DISALLOWED_REASON_LOCATION_DISABLED = 4; 1605 1606 /** @hide */ 1607 @IntDef(prefix = "SATELLITE_DISALLOWED_REASON_", value = { 1608 SATELLITE_DISALLOWED_REASON_NOT_SUPPORTED, 1609 SATELLITE_DISALLOWED_REASON_NOT_PROVISIONED, 1610 SATELLITE_DISALLOWED_REASON_NOT_IN_ALLOWED_REGION, 1611 SATELLITE_DISALLOWED_REASON_UNSUPPORTED_DEFAULT_MSG_APP, 1612 SATELLITE_DISALLOWED_REASON_LOCATION_DISABLED, 1613 }) 1614 @Retention(RetentionPolicy.SOURCE) 1615 public @interface SatelliteDisallowedReason {} 1616 1617 /** 1618 * Start receiving satellite transmission updates. 1619 * This can be called by the pointing UI when the user starts pointing to the satellite. 1620 * Modem should continue to report the pointing input as the device or satellite moves. 1621 * Satellite transmission updates are started only on {@link #SATELLITE_RESULT_SUCCESS}. 1622 * All other results indicate that this operation failed. 1623 * Once satellite transmission updates begin, position and datagram transfer state updates 1624 * will be sent through {@link SatelliteTransmissionUpdateCallback}. 1625 * 1626 * @param executor The executor on which the callback and error code listener will be called. 1627 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 1628 * @param callback The callback to notify of satellite transmission updates. 1629 * 1630 * @throws SecurityException if the caller doesn't have required permission. 1631 * 1632 * @hide 1633 */ 1634 @SystemApi 1635 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1636 @SuppressWarnings("SamShouldBeLast") startTransmissionUpdates(@onNull @allbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener, @NonNull SatelliteTransmissionUpdateCallback callback)1637 public void startTransmissionUpdates(@NonNull @CallbackExecutor Executor executor, 1638 @SatelliteResult @NonNull Consumer<Integer> resultListener, 1639 @NonNull SatelliteTransmissionUpdateCallback callback) { 1640 Objects.requireNonNull(executor); 1641 Objects.requireNonNull(resultListener); 1642 Objects.requireNonNull(callback); 1643 1644 try { 1645 ITelephony telephony = getITelephony(); 1646 if (telephony != null) { 1647 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 1648 @Override 1649 public void accept(int result) { 1650 executor.execute(() -> Binder.withCleanCallingIdentity( 1651 () -> resultListener.accept(result))); 1652 } 1653 }; 1654 ISatelliteTransmissionUpdateCallback internalCallback = 1655 new ISatelliteTransmissionUpdateCallback.Stub() { 1656 1657 @Override 1658 public void onSatellitePositionChanged(PointingInfo pointingInfo) { 1659 executor.execute(() -> Binder.withCleanCallingIdentity( 1660 () -> callback.onSatellitePositionChanged(pointingInfo))); 1661 } 1662 1663 @Override 1664 public void onSendDatagramStateChanged(int datagramType, int state, 1665 int sendPendingCount, int errorCode) { 1666 executor.execute(() -> Binder.withCleanCallingIdentity( 1667 () -> callback.onSendDatagramStateChanged(datagramType, 1668 state, sendPendingCount, errorCode))); 1669 1670 // For backward compatibility 1671 executor.execute(() -> Binder.withCleanCallingIdentity( 1672 () -> callback.onSendDatagramStateChanged( 1673 state, sendPendingCount, errorCode))); 1674 } 1675 1676 @Override 1677 public void onReceiveDatagramStateChanged(int state, 1678 int receivePendingCount, int errorCode) { 1679 executor.execute(() -> Binder.withCleanCallingIdentity( 1680 () -> callback.onReceiveDatagramStateChanged( 1681 state, receivePendingCount, errorCode))); 1682 } 1683 1684 @Override 1685 public void onSendDatagramRequested(int datagramType) { 1686 executor.execute(() -> Binder.withCleanCallingIdentity( 1687 () -> callback.onSendDatagramRequested(datagramType))); 1688 } 1689 }; 1690 sSatelliteTransmissionUpdateCallbackMap.put(callback, internalCallback); 1691 telephony.startSatelliteTransmissionUpdates(errorCallback, internalCallback); 1692 } else { 1693 loge("startTransmissionUpdates() invalid telephony"); 1694 executor.execute(() -> Binder.withCleanCallingIdentity( 1695 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1696 } 1697 } catch (RemoteException ex) { 1698 loge("startTransmissionUpdates() RemoteException: " + ex); 1699 executor.execute(() -> Binder.withCleanCallingIdentity( 1700 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1701 } 1702 } 1703 1704 /** 1705 * Stop receiving satellite transmission updates. 1706 * This can be called by the pointing UI when the user stops pointing to the satellite. 1707 * Satellite transmission updates are stopped and the callback is unregistered only on 1708 * {@link #SATELLITE_RESULT_SUCCESS}. All other results that this operation failed. 1709 * 1710 * @param callback The callback that was passed to {@link 1711 * #startTransmissionUpdates(Executor, Consumer, SatelliteTransmissionUpdateCallback)}. 1712 * @param executor The executor on which the error code listener will be called. 1713 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 1714 * 1715 * @throws SecurityException if the caller doesn't have required permission. 1716 * 1717 * @hide 1718 */ 1719 @SystemApi 1720 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) stopTransmissionUpdates(@onNull SatelliteTransmissionUpdateCallback callback, @SuppressWarnings("ListenerLast") @NonNull @CallbackExecutor Executor executor, @SuppressWarnings("ListenerLast") @SatelliteResult @NonNull Consumer<Integer> resultListener)1721 public void stopTransmissionUpdates(@NonNull SatelliteTransmissionUpdateCallback callback, 1722 @SuppressWarnings("ListenerLast") @NonNull @CallbackExecutor Executor executor, 1723 @SuppressWarnings("ListenerLast") @SatelliteResult @NonNull 1724 Consumer<Integer> resultListener) { 1725 Objects.requireNonNull(callback); 1726 Objects.requireNonNull(executor); 1727 Objects.requireNonNull(resultListener); 1728 1729 ISatelliteTransmissionUpdateCallback internalCallback = 1730 sSatelliteTransmissionUpdateCallbackMap.remove(callback); 1731 1732 try { 1733 ITelephony telephony = getITelephony(); 1734 if (telephony != null) { 1735 if (internalCallback != null) { 1736 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 1737 @Override 1738 public void accept(int result) { 1739 executor.execute(() -> Binder.withCleanCallingIdentity( 1740 () -> resultListener.accept(result))); 1741 } 1742 }; 1743 telephony.stopSatelliteTransmissionUpdates(errorCallback, internalCallback); 1744 // TODO: Notify SmsHandler that pointing UI stopped 1745 } else { 1746 loge("stopSatelliteTransmissionUpdates: No internal callback."); 1747 executor.execute(() -> Binder.withCleanCallingIdentity( 1748 () -> resultListener.accept(SATELLITE_RESULT_INVALID_ARGUMENTS))); 1749 } 1750 } else { 1751 loge("stopTransmissionUpdates() invalid telephony"); 1752 executor.execute(() -> Binder.withCleanCallingIdentity( 1753 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1754 } 1755 } catch (RemoteException ex) { 1756 loge("stopTransmissionUpdates() RemoteException: " + ex); 1757 executor.execute(() -> Binder.withCleanCallingIdentity( 1758 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1759 } 1760 } 1761 1762 /** 1763 * Provision the device with a satellite provider. 1764 * This is needed if the provider allows dynamic registration. 1765 * 1766 * @param token The token is generated by the user which is used as a unique identifier for 1767 * provisioning with satellite gateway. 1768 * @param provisionData Data from the provisioning app that can be used by provisioning server 1769 * @param cancellationSignal The optional signal used by the caller to cancel the provision 1770 * request. Even when the cancellation is signaled, Telephony will 1771 * still trigger the callback to return the result of this request. 1772 * @param executor The executor on which the error code listener will be called. 1773 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 1774 * 1775 * @throws SecurityException if the caller doesn't have required permission. 1776 * 1777 * @hide 1778 */ 1779 @SystemApi 1780 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) provisionService(@onNull String token, @NonNull byte[] provisionData, @Nullable CancellationSignal cancellationSignal, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)1781 public void provisionService(@NonNull String token, @NonNull byte[] provisionData, 1782 @Nullable CancellationSignal cancellationSignal, 1783 @NonNull @CallbackExecutor Executor executor, 1784 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 1785 Objects.requireNonNull(token); 1786 Objects.requireNonNull(executor); 1787 Objects.requireNonNull(resultListener); 1788 Objects.requireNonNull(provisionData); 1789 1790 ICancellationSignal cancelRemote = null; 1791 try { 1792 ITelephony telephony = getITelephony(); 1793 if (telephony != null) { 1794 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 1795 @Override 1796 public void accept(int result) { 1797 executor.execute(() -> Binder.withCleanCallingIdentity( 1798 () -> resultListener.accept(result))); 1799 } 1800 }; 1801 cancelRemote = telephony.provisionSatelliteService(token, provisionData, 1802 errorCallback); 1803 } else { 1804 loge("provisionService() invalid telephony"); 1805 executor.execute(() -> Binder.withCleanCallingIdentity( 1806 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1807 } 1808 } catch (RemoteException ex) { 1809 loge("provisionService() RemoteException=" + ex); 1810 executor.execute(() -> Binder.withCleanCallingIdentity( 1811 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1812 } 1813 if (cancellationSignal != null) { 1814 cancellationSignal.setRemote(cancelRemote); 1815 } 1816 } 1817 1818 /** 1819 * Deprovision the device with the satellite provider. 1820 * This is needed if the provider allows dynamic registration. Once deprovisioned, 1821 * {@link SatelliteProvisionStateCallback#onSatelliteProvisionStateChanged(boolean)} 1822 * should report as deprovisioned. 1823 * For provisioning satellite service, refer to 1824 * {@link #provisionService(String, byte[], CancellationSignal, Executor, Consumer)} 1825 * 1826 * @param token The token of the device/subscription to be deprovisioned. 1827 * This should match with the token passed as input in 1828 * {@link #provisionService(String, byte[], CancellationSignal, Executor, 1829 * Consumer)} 1830 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 1831 * 1832 * @throws SecurityException if the caller doesn't have required permission. 1833 * 1834 * @hide 1835 */ 1836 @SystemApi 1837 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) deprovisionService(@onNull String token, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)1838 public void deprovisionService(@NonNull String token, 1839 @NonNull @CallbackExecutor Executor executor, 1840 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 1841 Objects.requireNonNull(token); 1842 Objects.requireNonNull(executor); 1843 Objects.requireNonNull(resultListener); 1844 1845 try { 1846 ITelephony telephony = getITelephony(); 1847 if (telephony != null) { 1848 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 1849 @Override 1850 public void accept(int result) { 1851 executor.execute(() -> Binder.withCleanCallingIdentity( 1852 () -> resultListener.accept(result))); 1853 } 1854 }; 1855 telephony.deprovisionSatelliteService(token, errorCallback); 1856 } else { 1857 loge("deprovisionService() invalid telephony"); 1858 executor.execute(() -> Binder.withCleanCallingIdentity( 1859 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1860 } 1861 } catch (RemoteException ex) { 1862 loge("deprovisionService() RemoteException ex=" + ex); 1863 executor.execute(() -> Binder.withCleanCallingIdentity( 1864 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1865 } 1866 } 1867 1868 /** 1869 * Registers for the satellite provision state changed. 1870 * 1871 * @param executor The executor on which the callback will be called. 1872 * @param callback The callback to handle the satellite provision state changed event. 1873 * 1874 * @return The {@link SatelliteResult} result of the operation. 1875 * 1876 * @throws SecurityException if the caller doesn't have required permission. 1877 * @throws IllegalStateException if the Telephony process is not currently available. 1878 * 1879 * @hide 1880 */ 1881 @SystemApi 1882 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) registerForProvisionStateChanged( @onNull @allbackExecutor Executor executor, @NonNull SatelliteProvisionStateCallback callback)1883 @SatelliteResult public int registerForProvisionStateChanged( 1884 @NonNull @CallbackExecutor Executor executor, 1885 @NonNull SatelliteProvisionStateCallback callback) { 1886 Objects.requireNonNull(executor); 1887 Objects.requireNonNull(callback); 1888 1889 try { 1890 ITelephony telephony = getITelephony(); 1891 if (telephony != null) { 1892 ISatelliteProvisionStateCallback internalCallback = 1893 new ISatelliteProvisionStateCallback.Stub() { 1894 @Override 1895 public void onSatelliteProvisionStateChanged(boolean provisioned) { 1896 executor.execute(() -> Binder.withCleanCallingIdentity( 1897 () -> callback.onSatelliteProvisionStateChanged( 1898 provisioned))); 1899 } 1900 1901 @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) 1902 @Override 1903 public void onSatelliteSubscriptionProvisionStateChanged( 1904 @NonNull List<SatelliteSubscriberProvisionStatus> 1905 satelliteSubscriberProvisionStatus) { 1906 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1907 callback.onSatelliteSubscriptionProvisionStateChanged( 1908 satelliteSubscriberProvisionStatus))); 1909 } 1910 }; 1911 sSatelliteProvisionStateCallbackMap.put(callback, internalCallback); 1912 return telephony.registerForSatelliteProvisionStateChanged(internalCallback); 1913 } else { 1914 throw new IllegalStateException("telephony service is null."); 1915 } 1916 } catch (RemoteException ex) { 1917 loge("registerForProvisionStateChanged() RemoteException: " + ex); 1918 ex.rethrowAsRuntimeException(); 1919 } 1920 return SATELLITE_RESULT_REQUEST_FAILED; 1921 } 1922 1923 /** 1924 * Unregisters for the satellite provision state changed. 1925 * If callback was not registered before, the request will be ignored. 1926 * 1927 * @param callback The callback that was passed to 1928 * {@link #registerForProvisionStateChanged(Executor, SatelliteProvisionStateCallback)} 1929 * 1930 * @throws SecurityException if the caller doesn't have required permission. 1931 * @throws IllegalStateException if the Telephony process is not currently available. 1932 * 1933 * @hide 1934 */ 1935 @SystemApi 1936 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) unregisterForProvisionStateChanged( @onNull SatelliteProvisionStateCallback callback)1937 public void unregisterForProvisionStateChanged( 1938 @NonNull SatelliteProvisionStateCallback callback) { 1939 Objects.requireNonNull(callback); 1940 ISatelliteProvisionStateCallback internalCallback = 1941 sSatelliteProvisionStateCallbackMap.remove(callback); 1942 1943 try { 1944 ITelephony telephony = getITelephony(); 1945 if (telephony != null) { 1946 if (internalCallback != null) { 1947 telephony.unregisterForSatelliteProvisionStateChanged(internalCallback); 1948 } else { 1949 loge("unregisterForProvisionStateChanged: No internal callback."); 1950 } 1951 } else { 1952 throw new IllegalStateException("telephony service is null."); 1953 } 1954 } catch (RemoteException ex) { 1955 loge("unregisterForProvisionStateChanged() RemoteException: " + ex); 1956 ex.rethrowAsRuntimeException(); 1957 } 1958 } 1959 1960 /** 1961 * Request to get whether this device is provisioned with a satellite provider. 1962 * 1963 * @param executor The executor on which the callback will be called. 1964 * @param callback The callback object to which the result will be delivered. 1965 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 1966 * will return a {@code boolean} with value {@code true} if the device is 1967 * provisioned with a satellite provider and {@code false} otherwise. 1968 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 1969 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 1970 * 1971 * @throws SecurityException if the caller doesn't have required permission. 1972 * 1973 * @hide 1974 */ 1975 @SystemApi 1976 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) requestIsProvisioned(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteException> callback)1977 public void requestIsProvisioned(@NonNull @CallbackExecutor Executor executor, 1978 @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { 1979 Objects.requireNonNull(executor); 1980 Objects.requireNonNull(callback); 1981 1982 try { 1983 ITelephony telephony = getITelephony(); 1984 if (telephony != null) { 1985 ResultReceiver receiver = new ResultReceiver(null) { 1986 @Override 1987 protected void onReceiveResult(int resultCode, Bundle resultData) { 1988 if (resultCode == SATELLITE_RESULT_SUCCESS) { 1989 if (resultData.containsKey(KEY_SATELLITE_PROVISIONED)) { 1990 boolean isSatelliteProvisioned = 1991 resultData.getBoolean(KEY_SATELLITE_PROVISIONED); 1992 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1993 callback.onResult(isSatelliteProvisioned))); 1994 } else { 1995 loge("KEY_SATELLITE_PROVISIONED does not exist."); 1996 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1997 callback.onError(new SatelliteException( 1998 SATELLITE_RESULT_REQUEST_FAILED)))); 1999 } 2000 } else { 2001 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2002 callback.onError(new SatelliteException(resultCode)))); 2003 } 2004 } 2005 }; 2006 telephony.requestIsSatelliteProvisioned(receiver); 2007 } else { 2008 loge("requestIsProvisioned() invalid telephony"); 2009 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 2010 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 2011 } 2012 } catch (RemoteException ex) { 2013 loge("requestIsProvisioned() RemoteException: " + ex); 2014 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 2015 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 2016 } 2017 } 2018 2019 /** 2020 * Registers for modem state changed from satellite modem. 2021 * 2022 * @param executor The executor on which the callback will be called. 2023 * @param callback The callback to handle the satellite modem state changed event. 2024 * 2025 * @return The {@link SatelliteResult} result of the operation. 2026 * 2027 * @throws SecurityException if the caller doesn't have required permission. 2028 * @throws IllegalStateException if the Telephony process is not currently available. 2029 * 2030 * @hide 2031 */ 2032 @SystemApi 2033 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) registerForModemStateChanged( @onNull @allbackExecutor Executor executor, @NonNull SatelliteModemStateCallback callback)2034 @SatelliteResult public int registerForModemStateChanged( 2035 @NonNull @CallbackExecutor Executor executor, 2036 @NonNull SatelliteModemStateCallback callback) { 2037 Objects.requireNonNull(executor); 2038 Objects.requireNonNull(callback); 2039 2040 try { 2041 ITelephony telephony = getITelephony(); 2042 if (telephony != null) { 2043 ISatelliteModemStateCallback internalCallback = 2044 new ISatelliteModemStateCallback.Stub() { 2045 @Override 2046 public void onSatelliteModemStateChanged(int state) { 2047 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2048 callback.onSatelliteModemStateChanged(state))); 2049 } 2050 2051 @Override 2052 public void onEmergencyModeChanged(boolean isEmergency) { 2053 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2054 callback.onEmergencyModeChanged(isEmergency))); 2055 } 2056 2057 @Hide 2058 @Override 2059 public void onRegistrationFailure(int causeCode) { 2060 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2061 callback.onRegistrationFailure(causeCode))); 2062 } 2063 2064 @Override 2065 public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) { 2066 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2067 callback.onTerrestrialNetworkAvailableChanged(isAvailable))); 2068 } 2069 }; 2070 sSatelliteModemStateCallbackMap.put(callback, internalCallback); 2071 return telephony.registerForSatelliteModemStateChanged(internalCallback); 2072 } else { 2073 throw new IllegalStateException("telephony service is null."); 2074 } 2075 } catch (RemoteException ex) { 2076 loge("registerForModemStateChanged() RemoteException:" + ex); 2077 ex.rethrowAsRuntimeException(); 2078 } 2079 return SATELLITE_RESULT_REQUEST_FAILED; 2080 } 2081 2082 /** 2083 * Unregisters for modem state changed from satellite modem. 2084 * If callback was not registered before, the request will be ignored. 2085 * 2086 * @param callback The callback that was passed to 2087 * {@link #registerForModemStateChanged(Executor, SatelliteModemStateCallback)}. 2088 * 2089 * @throws SecurityException if the caller doesn't have required permission. 2090 * @throws IllegalStateException if the Telephony process is not currently available. 2091 * 2092 * @hide 2093 */ 2094 @SystemApi 2095 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) unregisterForModemStateChanged( @onNull SatelliteModemStateCallback callback)2096 public void unregisterForModemStateChanged( 2097 @NonNull SatelliteModemStateCallback callback) { 2098 Objects.requireNonNull(callback); 2099 ISatelliteModemStateCallback internalCallback = sSatelliteModemStateCallbackMap.remove( 2100 callback); 2101 2102 try { 2103 ITelephony telephony = getITelephony(); 2104 if (telephony != null) { 2105 if (internalCallback != null) { 2106 telephony.unregisterForModemStateChanged(internalCallback); 2107 } else { 2108 loge("unregisterForModemStateChanged: No internal callback."); 2109 } 2110 } else { 2111 throw new IllegalStateException("telephony service is null."); 2112 } 2113 } catch (RemoteException ex) { 2114 loge("unregisterForModemStateChanged() RemoteException:" + ex); 2115 ex.rethrowAsRuntimeException(); 2116 } 2117 } 2118 2119 /** 2120 * Register to receive incoming datagrams over satellite. 2121 * 2122 * To poll for pending satellite datagrams, refer to 2123 * {@link #pollPendingDatagrams(Executor, Consumer)} 2124 * 2125 * @param executor The executor on which the callback will be called. 2126 * @param callback The callback to handle incoming datagrams over satellite. 2127 * This callback with be invoked when a new datagram is received from satellite. 2128 * 2129 * @return The {@link SatelliteResult} result of the operation. 2130 * 2131 * @throws SecurityException if the caller doesn't have required permission. 2132 * @throws IllegalStateException if the Telephony process is not currently available. 2133 * 2134 * @hide 2135 */ 2136 @SystemApi 2137 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) registerForIncomingDatagram( @onNull @allbackExecutor Executor executor, @NonNull SatelliteDatagramCallback callback)2138 @SatelliteResult public int registerForIncomingDatagram( 2139 @NonNull @CallbackExecutor Executor executor, 2140 @NonNull SatelliteDatagramCallback callback) { 2141 Objects.requireNonNull(executor); 2142 Objects.requireNonNull(callback); 2143 2144 try { 2145 ITelephony telephony = getITelephony(); 2146 if (telephony != null) { 2147 ISatelliteDatagramCallback internalCallback = 2148 new ISatelliteDatagramCallback.Stub() { 2149 @Override 2150 public void onSatelliteDatagramReceived(long datagramId, 2151 @NonNull SatelliteDatagram datagram, int pendingCount, 2152 @NonNull IVoidConsumer internalAck) { 2153 Consumer<Void> externalAck = new Consumer<Void>() { 2154 @Override 2155 public void accept(Void result) { 2156 try { 2157 internalAck.accept(); 2158 } catch (RemoteException e) { 2159 logd("onSatelliteDatagramReceived " 2160 + "RemoteException: " + e); 2161 } 2162 } 2163 }; 2164 2165 executor.execute(() -> Binder.withCleanCallingIdentity( 2166 () -> callback.onSatelliteDatagramReceived( 2167 datagramId, datagram, pendingCount, externalAck))); 2168 } 2169 }; 2170 sSatelliteDatagramCallbackMap.put(callback, internalCallback); 2171 return telephony.registerForIncomingDatagram(internalCallback); 2172 } else { 2173 throw new IllegalStateException("telephony service is null."); 2174 } 2175 } catch (RemoteException ex) { 2176 loge("registerForIncomingDatagram() RemoteException:" + ex); 2177 ex.rethrowAsRuntimeException(); 2178 } 2179 return SATELLITE_RESULT_REQUEST_FAILED; 2180 } 2181 2182 /** 2183 * Unregister to stop receiving incoming datagrams over satellite. 2184 * If callback was not registered before, the request will be ignored. 2185 * 2186 * @param callback The callback that was passed to 2187 * {@link #registerForIncomingDatagram(Executor, SatelliteDatagramCallback)}. 2188 * 2189 * @throws SecurityException if the caller doesn't have required permission. 2190 * @throws IllegalStateException if the Telephony process is not currently available. 2191 * 2192 * @hide 2193 */ 2194 @SystemApi 2195 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) unregisterForIncomingDatagram(@onNull SatelliteDatagramCallback callback)2196 public void unregisterForIncomingDatagram(@NonNull SatelliteDatagramCallback callback) { 2197 Objects.requireNonNull(callback); 2198 ISatelliteDatagramCallback internalCallback = 2199 sSatelliteDatagramCallbackMap.remove(callback); 2200 2201 try { 2202 ITelephony telephony = getITelephony(); 2203 if (telephony != null) { 2204 if (internalCallback != null) { 2205 telephony.unregisterForIncomingDatagram(internalCallback); 2206 } else { 2207 loge("unregisterForIncomingDatagram: No internal callback."); 2208 } 2209 } else { 2210 throw new IllegalStateException("telephony service is null."); 2211 } 2212 } catch (RemoteException ex) { 2213 loge("unregisterForIncomingDatagram() RemoteException:" + ex); 2214 ex.rethrowAsRuntimeException(); 2215 } 2216 } 2217 2218 /** 2219 * Poll pending satellite datagrams over satellite. 2220 * 2221 * This method should be called when user specifies to check incoming messages over satellite. 2222 * This method requests modem to check if there are any pending datagrams to be received over 2223 * satellite. If there are any incoming datagrams, they will be received via 2224 * {@link SatelliteDatagramCallback#onSatelliteDatagramReceived(long, SatelliteDatagram, int, 2225 * Consumer)} )} 2226 * 2227 * @param executor The executor on which the result listener will be called. 2228 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 2229 * 2230 * @throws SecurityException if the caller doesn't have required permission. 2231 * 2232 * @hide 2233 */ 2234 @SystemApi 2235 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) pollPendingDatagrams(@onNull @allbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)2236 public void pollPendingDatagrams(@NonNull @CallbackExecutor Executor executor, 2237 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 2238 Objects.requireNonNull(executor); 2239 Objects.requireNonNull(resultListener); 2240 2241 try { 2242 ITelephony telephony = getITelephony(); 2243 if (telephony != null) { 2244 IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() { 2245 @Override 2246 public void accept(int result) { 2247 executor.execute(() -> Binder.withCleanCallingIdentity( 2248 () -> resultListener.accept(result))); 2249 } 2250 }; 2251 telephony.pollPendingDatagrams(internalCallback); 2252 } else { 2253 loge("pollPendingDatagrams() invalid telephony"); 2254 executor.execute(() -> Binder.withCleanCallingIdentity( 2255 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 2256 } 2257 } catch (RemoteException ex) { 2258 loge("pollPendingDatagrams() RemoteException:" + ex); 2259 executor.execute(() -> Binder.withCleanCallingIdentity( 2260 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 2261 } 2262 } 2263 2264 /** 2265 * Send datagram over satellite. 2266 * 2267 * Gateway encodes SOS message or location sharing message into a datagram and passes it as 2268 * input to this method. Datagram received here will be passed down to modem without any 2269 * encoding or encryption. 2270 * 2271 * @param datagramType datagram type indicating whether the datagram is of type 2272 * SOS_SMS or LOCATION_SHARING. 2273 * @param datagram encoded gateway datagram which is encrypted by the caller. 2274 * Datagram will be passed down to modem without any encoding or encryption. 2275 * @param needFullScreenPointingUI If set to true, this indicates pointingUI app to open in full 2276 * screen mode if satellite communication needs pointingUI. 2277 * If this is set to false, pointingUI may be presented to the 2278 * user in collapsed view. Application may decide to mark this 2279 * flag as true when the user is sending data for the first time 2280 * or whenever there is a considerable idle time between 2281 * satellite activity. This decision should be done based upon 2282 * user activity and the application's ability to determine the 2283 * best possible UX experience for the user. 2284 * @param executor The executor on which the result listener will be called. 2285 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 2286 * 2287 * @throws SecurityException if the caller doesn't have required permission. 2288 * 2289 * @hide 2290 */ 2291 @SystemApi 2292 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) sendDatagram(@atagramType int datagramType, @NonNull SatelliteDatagram datagram, boolean needFullScreenPointingUI, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)2293 public void sendDatagram(@DatagramType int datagramType, 2294 @NonNull SatelliteDatagram datagram, boolean needFullScreenPointingUI, 2295 @NonNull @CallbackExecutor Executor executor, 2296 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 2297 Objects.requireNonNull(datagram); 2298 Objects.requireNonNull(executor); 2299 Objects.requireNonNull(resultListener); 2300 2301 try { 2302 ITelephony telephony = getITelephony(); 2303 if (telephony != null) { 2304 IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() { 2305 @Override 2306 public void accept(int result) { 2307 executor.execute(() -> Binder.withCleanCallingIdentity( 2308 () -> resultListener.accept(result))); 2309 } 2310 }; 2311 telephony.sendDatagram(datagramType, datagram, 2312 needFullScreenPointingUI, internalCallback); 2313 } else { 2314 loge("sendDatagram() invalid telephony"); 2315 executor.execute(() -> Binder.withCleanCallingIdentity( 2316 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 2317 } 2318 } catch (RemoteException ex) { 2319 loge("sendDatagram() RemoteException:" + ex); 2320 executor.execute(() -> Binder.withCleanCallingIdentity( 2321 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 2322 } 2323 } 2324 2325 /** 2326 * Request to get whether satellite communication is allowed for the current location. 2327 * 2328 * @param executor The executor on which the callback will be called. 2329 * @param callback The callback object to which the result will be delivered. 2330 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 2331 * will return a {@code boolean} with value {@code true} if satellite 2332 * communication is allowed for the current location and 2333 * {@code false} otherwise. 2334 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 2335 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 2336 * 2337 * @throws SecurityException if the caller doesn't have required permission. 2338 * 2339 * @hide 2340 */ 2341 @SystemApi 2342 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) requestIsCommunicationAllowedForCurrentLocation( @onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteException> callback)2343 public void requestIsCommunicationAllowedForCurrentLocation( 2344 @NonNull @CallbackExecutor Executor executor, 2345 @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { 2346 Objects.requireNonNull(executor); 2347 Objects.requireNonNull(callback); 2348 2349 try { 2350 ITelephony telephony = getITelephony(); 2351 if (telephony != null) { 2352 ResultReceiver receiver = new ResultReceiver(null) { 2353 @Override 2354 protected void onReceiveResult(int resultCode, Bundle resultData) { 2355 if (resultCode == SATELLITE_RESULT_SUCCESS) { 2356 if (resultData.containsKey(KEY_SATELLITE_COMMUNICATION_ALLOWED)) { 2357 boolean isSatelliteCommunicationAllowed = 2358 resultData.getBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED); 2359 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2360 callback.onResult(isSatelliteCommunicationAllowed))); 2361 } else { 2362 loge("KEY_SATELLITE_COMMUNICATION_ALLOWED does not exist."); 2363 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2364 callback.onError(new SatelliteException( 2365 SATELLITE_RESULT_REQUEST_FAILED)))); 2366 } 2367 } else { 2368 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2369 callback.onError(new SatelliteException(resultCode)))); 2370 } 2371 } 2372 }; 2373 telephony.requestIsCommunicationAllowedForCurrentLocation(mSubId, receiver); 2374 } else { 2375 loge("requestIsCommunicationAllowedForCurrentLocation() invalid telephony"); 2376 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 2377 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 2378 } 2379 } catch (RemoteException ex) { 2380 loge("requestIsCommunicationAllowedForCurrentLocation() RemoteException: " + ex); 2381 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 2382 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 2383 } 2384 } 2385 2386 /** 2387 * Request to get satellite access configuration for the current location. 2388 * 2389 * @param executor The executor on which the callback will be called. 2390 * @param callback The callback object to which the result will be delivered. 2391 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 2392 * will return a {@code SatelliteAccessConfiguration} with value the regional 2393 * satellite access configuration at the current location. 2394 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 2395 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 2396 * 2397 * @throws SecurityException if the caller doesn't have required permission. 2398 * 2399 * @hide 2400 */ 2401 @SystemApi 2402 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2403 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) requestSatelliteAccessConfigurationForCurrentLocation( @onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<SatelliteAccessConfiguration, SatelliteException> callback)2404 public void requestSatelliteAccessConfigurationForCurrentLocation( 2405 @NonNull @CallbackExecutor Executor executor, 2406 @NonNull OutcomeReceiver<SatelliteAccessConfiguration, SatelliteException> callback) { 2407 Objects.requireNonNull(executor); 2408 Objects.requireNonNull(callback); 2409 2410 try { 2411 ITelephony telephony = getITelephony(); 2412 if (telephony != null) { 2413 ResultReceiver receiver = new ResultReceiver(null) { 2414 @Override 2415 protected void onReceiveResult(int resultCode, Bundle resultData) { 2416 if (resultCode == SATELLITE_RESULT_SUCCESS) { 2417 if (resultData.containsKey(KEY_SATELLITE_ACCESS_CONFIGURATION)) { 2418 SatelliteAccessConfiguration satelliteAccessConfiguration = 2419 resultData.getParcelable(KEY_SATELLITE_ACCESS_CONFIGURATION, 2420 SatelliteAccessConfiguration.class); 2421 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2422 callback.onResult(satelliteAccessConfiguration))); 2423 } else { 2424 loge("KEY_SATELLITE_ACCESS_CONFIGURATION does not exist."); 2425 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2426 callback.onError(new SatelliteException( 2427 SATELLITE_RESULT_REQUEST_FAILED)))); 2428 } 2429 } else { 2430 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2431 callback.onError(new SatelliteException(resultCode)))); 2432 } 2433 } 2434 }; 2435 telephony.requestSatelliteAccessConfigurationForCurrentLocation(receiver); 2436 } else { 2437 loge("requestSatelliteAccessConfigurationForCurrentLocation() invalid telephony"); 2438 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 2439 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 2440 } 2441 } catch (RemoteException ex) { 2442 loge("requestSatelliteAccessConfigurationForCurrentLocation() RemoteException: " 2443 + ex); 2444 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 2445 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 2446 } 2447 } 2448 2449 /** 2450 * Request to get the duration in seconds after which the satellite will be visible. 2451 * This will be {@link Duration#ZERO} if the satellite is currently visible. 2452 * 2453 * @param executor The executor on which the callback will be called. 2454 * @param callback The callback object to which the result will be delivered. 2455 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 2456 * will return the time after which the satellite will be visible. 2457 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 2458 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 2459 * 2460 * @throws SecurityException if the caller doesn't have required permission. 2461 * 2462 * @hide 2463 */ 2464 @SystemApi 2465 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) requestTimeForNextSatelliteVisibility(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<Duration, SatelliteException> callback)2466 public void requestTimeForNextSatelliteVisibility(@NonNull @CallbackExecutor Executor executor, 2467 @NonNull OutcomeReceiver<Duration, SatelliteException> callback) { 2468 Objects.requireNonNull(executor); 2469 Objects.requireNonNull(callback); 2470 2471 try { 2472 ITelephony telephony = getITelephony(); 2473 if (telephony != null) { 2474 ResultReceiver receiver = new ResultReceiver(null) { 2475 @Override 2476 protected void onReceiveResult(int resultCode, Bundle resultData) { 2477 if (resultCode == SATELLITE_RESULT_SUCCESS) { 2478 if (resultData.containsKey(KEY_SATELLITE_NEXT_VISIBILITY)) { 2479 int nextVisibilityDuration = 2480 resultData.getInt(KEY_SATELLITE_NEXT_VISIBILITY); 2481 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2482 callback.onResult( 2483 Duration.ofSeconds(nextVisibilityDuration)))); 2484 } else { 2485 loge("KEY_SATELLITE_NEXT_VISIBILITY does not exist."); 2486 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2487 callback.onError(new SatelliteException( 2488 SATELLITE_RESULT_REQUEST_FAILED)))); 2489 } 2490 } else { 2491 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2492 callback.onError(new SatelliteException(resultCode)))); 2493 } 2494 } 2495 }; 2496 telephony.requestTimeForNextSatelliteVisibility(receiver); 2497 } else { 2498 loge("requestTimeForNextSatelliteVisibility() invalid telephony"); 2499 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 2500 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 2501 } 2502 } catch (RemoteException ex) { 2503 loge("requestTimeForNextSatelliteVisibility() RemoteException: " + ex); 2504 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 2505 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 2506 } 2507 } 2508 2509 /** 2510 * Request to get the currently selected satellite subscription id as an {@link Integer}. 2511 * 2512 * @param executor The executor on which the callback will be called. 2513 * @param callback The callback object to which the result will be delivered. 2514 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 2515 * will return the selected NB IOT satellite subscription ID. 2516 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 2517 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 2518 * 2519 * @throws SecurityException if the caller doesn't have required permission. 2520 * 2521 * @hide 2522 */ 2523 @SystemApi 2524 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 2525 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) requestSelectedNbIotSatelliteSubscriptionId( @onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<Integer, SatelliteException> callback)2526 public void requestSelectedNbIotSatelliteSubscriptionId( 2527 @NonNull @CallbackExecutor Executor executor, 2528 @NonNull OutcomeReceiver<Integer, SatelliteException> callback) { 2529 Objects.requireNonNull(executor); 2530 Objects.requireNonNull(callback); 2531 2532 try { 2533 ITelephony telephony = getITelephony(); 2534 if (telephony != null) { 2535 ResultReceiver receiver = new ResultReceiver(null) { 2536 @Override 2537 protected void onReceiveResult(int resultCode, Bundle resultData) { 2538 if (resultCode == SATELLITE_RESULT_SUCCESS) { 2539 if (resultData 2540 .containsKey(KEY_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_ID)) { 2541 int selectedSatelliteSubscriptionId = 2542 resultData 2543 .getInt(KEY_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_ID); 2544 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2545 callback.onResult(selectedSatelliteSubscriptionId))); 2546 } else { 2547 loge( 2548 "KEY_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_ID does not exist." 2549 ); 2550 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2551 callback.onError(new SatelliteException( 2552 SATELLITE_RESULT_REQUEST_FAILED)))); 2553 } 2554 } else { 2555 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2556 callback.onError(new SatelliteException(resultCode)))); 2557 } 2558 } 2559 }; 2560 telephony.requestSelectedNbIotSatelliteSubscriptionId(receiver); 2561 } else { 2562 loge("requestSelectedNbIotSatelliteSubscriptionId() invalid telephony"); 2563 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 2564 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 2565 } 2566 } catch (RemoteException ex) { 2567 loge("requestSelectedNbIotSatelliteSubscriptionId() RemoteException: " + ex); 2568 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 2569 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 2570 } 2571 } 2572 2573 /** 2574 * Registers for selected satellite subscription changed event from the satellite service. 2575 * 2576 * @param executor The executor on which the callback will be called. 2577 * @param callback The callback to handle the selected satellite subscription changed event. 2578 * 2579 * @return The {@link SatelliteResult} result of the operation. 2580 * 2581 * @throws SecurityException if the caller doesn't have required permission. 2582 * @throws IllegalStateException if the Telephony process is not currently available. 2583 * 2584 * @hide 2585 */ 2586 @SystemApi 2587 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 2588 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) registerForSelectedNbIotSatelliteSubscriptionChanged( @onNull @allbackExecutor Executor executor, @NonNull SelectedNbIotSatelliteSubscriptionCallback callback)2589 @SatelliteResult public int registerForSelectedNbIotSatelliteSubscriptionChanged( 2590 @NonNull @CallbackExecutor Executor executor, 2591 @NonNull SelectedNbIotSatelliteSubscriptionCallback callback) { 2592 Objects.requireNonNull(executor); 2593 Objects.requireNonNull(callback); 2594 2595 try { 2596 ITelephony telephony = getITelephony(); 2597 if (telephony != null) { 2598 ISelectedNbIotSatelliteSubscriptionCallback internalCallback = 2599 new ISelectedNbIotSatelliteSubscriptionCallback.Stub() { 2600 @Override 2601 public void onSelectedNbIotSatelliteSubscriptionChanged( 2602 int selectedSubId) { 2603 executor.execute(() -> Binder.withCleanCallingIdentity( 2604 () -> callback.onSelectedNbIotSatelliteSubscriptionChanged( 2605 selectedSubId))); 2606 } 2607 }; 2608 sSelectedNbIotSatelliteSubscriptionCallbackMap.put(callback, internalCallback); 2609 return telephony.registerForSelectedNbIotSatelliteSubscriptionChanged( 2610 internalCallback); 2611 } else { 2612 throw new IllegalStateException("Telephony service is null."); 2613 } 2614 } catch (RemoteException ex) { 2615 loge("registerForSelectedNbIotSatelliteSubscriptionChanged() RemoteException: " + ex); 2616 ex.rethrowFromSystemServer(); 2617 } 2618 return SATELLITE_RESULT_REQUEST_FAILED; 2619 } 2620 2621 /** 2622 * Unregisters for selected satellite subscription changed event from the satellite service. If 2623 * callback was not registered before, the request will be ignored. 2624 * 2625 * @param callback The callback that was passed to {@link 2626 * #registerForSelectedNbIotSatelliteSubscriptionChanged(Executor, 2627 * SelectedNbIotSatelliteSubscriptionCallback)}. 2628 * 2629 * @throws SecurityException if the caller doesn't have required permission. 2630 * @throws IllegalStateException if the Telephony process is not currently available. 2631 * @hide 2632 */ 2633 @SystemApi 2634 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 2635 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) unregisterForSelectedNbIotSatelliteSubscriptionChanged( @onNull SelectedNbIotSatelliteSubscriptionCallback callback)2636 public void unregisterForSelectedNbIotSatelliteSubscriptionChanged( 2637 @NonNull SelectedNbIotSatelliteSubscriptionCallback callback) { 2638 Objects.requireNonNull(callback); 2639 ISelectedNbIotSatelliteSubscriptionCallback internalCallback = 2640 sSelectedNbIotSatelliteSubscriptionCallbackMap.remove(callback); 2641 2642 try { 2643 ITelephony telephony = getITelephony(); 2644 if (telephony != null) { 2645 if (internalCallback != null) { 2646 telephony.unregisterForSelectedNbIotSatelliteSubscriptionChanged( 2647 internalCallback); 2648 } else { 2649 loge("unregisterForSelectedNbIotSatelliteSubscriptionChanged: " + 2650 "No internal callback."); 2651 } 2652 } else { 2653 throw new IllegalStateException("Telephony service is null."); 2654 } 2655 } catch (RemoteException ex) { 2656 loge("unregisterForSelectedNbIotSatelliteSubscriptionChanged() RemoteException: " + 2657 ex); 2658 ex.rethrowFromSystemServer(); 2659 } 2660 } 2661 2662 /** 2663 * Inform whether the device is aligned with the satellite in both real and demo mode. 2664 * 2665 * In demo mode, framework will send datagram to modem only when device is aligned with 2666 * the satellite. This method helps framework to simulate the experience of sending datagram 2667 * over satellite. 2668 * 2669 * @param isAligned {code @true} Device is aligned with the satellite 2670 * {code @false} Device is not aligned with the satellite 2671 * 2672 * @throws SecurityException if the caller doesn't have required permission. 2673 * @throws IllegalStateException if the Telephony process is not currently available. 2674 * 2675 * @hide 2676 */ 2677 @SystemApi 2678 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) setDeviceAlignedWithSatellite(boolean isAligned)2679 public void setDeviceAlignedWithSatellite(boolean isAligned) { 2680 try { 2681 ITelephony telephony = getITelephony(); 2682 if (telephony != null) { 2683 telephony.setDeviceAlignedWithSatellite(isAligned); 2684 } else { 2685 throw new IllegalStateException("telephony service is null."); 2686 } 2687 } catch (RemoteException ex) { 2688 loge("setDeviceAlignedWithSatellite() RemoteException:" + ex); 2689 ex.rethrowAsRuntimeException(); 2690 } 2691 } 2692 2693 /** 2694 * User request to enable or disable carrier supported satellite plmn scan and attach by modem. 2695 * <p> 2696 * This API should be called by only settings app to pass down the user input for 2697 * enabling/disabling satellite. This user input will be persisted across device reboots. 2698 * <p> 2699 * Satellite will be enabled only when the following conditions are met: 2700 * <ul> 2701 * <li>Users want to enable it.</li> 2702 * <li>There is no satellite communication restriction, which is added by 2703 * {@link #addAttachRestrictionForCarrier(int, int, Executor, Consumer)}</li> 2704 * <li>The carrier config {@link 2705 * CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} is set to 2706 * {@code true}.</li> 2707 * </ul> 2708 * 2709 * @param subId The subscription ID of the carrier. 2710 * @param enableSatellite {@code true} to enable the satellite and {@code false} to disable. 2711 * @param executor The executor on which the error code listener will be called. 2712 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 2713 * 2714 * @throws SecurityException if the caller doesn't have required permission. 2715 * @throws IllegalArgumentException if the subscription is invalid. 2716 * 2717 * @hide 2718 */ 2719 @SystemApi 2720 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) requestAttachEnabledForCarrier(int subId, boolean enableSatellite, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)2721 public void requestAttachEnabledForCarrier(int subId, boolean enableSatellite, 2722 @NonNull @CallbackExecutor Executor executor, 2723 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 2724 Objects.requireNonNull(executor); 2725 Objects.requireNonNull(resultListener); 2726 2727 if (enableSatellite) { 2728 removeAttachRestrictionForCarrier(subId, 2729 SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, executor, resultListener); 2730 } else { 2731 addAttachRestrictionForCarrier(subId, 2732 SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, executor, resultListener); 2733 } 2734 } 2735 2736 /** 2737 * Request to get whether the carrier supported satellite plmn scan and attach by modem is 2738 * enabled by user. 2739 * 2740 * @param subId The subscription ID of the carrier. 2741 * @param executor The executor on which the callback will be called. 2742 * @param callback The callback object to which the result will be delivered. 2743 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 2744 * will return a {@code boolean} with value {@code true} if the satellite 2745 * is enabled and {@code false} otherwise. 2746 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 2747 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 2748 * 2749 * @throws SecurityException if the caller doesn't have required permission. 2750 * @throws IllegalStateException if the Telephony process is not currently available. 2751 * @throws IllegalArgumentException if the subscription is invalid. 2752 * 2753 * @hide 2754 */ 2755 @SystemApi 2756 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) requestIsAttachEnabledForCarrier(int subId, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteException> callback)2757 public void requestIsAttachEnabledForCarrier(int subId, 2758 @NonNull @CallbackExecutor Executor executor, 2759 @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { 2760 Objects.requireNonNull(executor); 2761 Objects.requireNonNull(callback); 2762 2763 Set<Integer> restrictionReason = getAttachRestrictionReasonsForCarrier(subId); 2764 executor.execute(() -> callback.onResult( 2765 !restrictionReason.contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER))); 2766 } 2767 2768 /** 2769 * Add a restriction reason for disallowing carrier supported satellite plmn scan and attach 2770 * by modem. 2771 * 2772 * @param subId The subscription ID of the carrier. 2773 * @param reason Reason for disallowing satellite communication. 2774 * @param executor The executor on which the error code listener will be called. 2775 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 2776 * 2777 * @throws SecurityException if the caller doesn't have required permission. 2778 * @throws IllegalArgumentException if the subscription is invalid. 2779 * 2780 * @hide 2781 */ 2782 @SystemApi 2783 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) addAttachRestrictionForCarrier(int subId, @SatelliteCommunicationRestrictionReason int reason, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)2784 public void addAttachRestrictionForCarrier(int subId, 2785 @SatelliteCommunicationRestrictionReason int reason, 2786 @NonNull @CallbackExecutor Executor executor, 2787 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 2788 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 2789 throw new IllegalArgumentException("Invalid subscription ID"); 2790 } 2791 2792 try { 2793 ITelephony telephony = getITelephony(); 2794 if (telephony != null) { 2795 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 2796 @Override 2797 public void accept(int result) { 2798 executor.execute(() -> Binder.withCleanCallingIdentity( 2799 () -> resultListener.accept(result))); 2800 } 2801 }; 2802 telephony.addAttachRestrictionForCarrier(subId, reason, errorCallback); 2803 } else { 2804 loge("addAttachRestrictionForCarrier() invalid telephony"); 2805 executor.execute(() -> Binder.withCleanCallingIdentity( 2806 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 2807 } 2808 } catch (RemoteException ex) { 2809 loge("addAttachRestrictionForCarrier() RemoteException:" + ex); 2810 executor.execute(() -> Binder.withCleanCallingIdentity( 2811 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 2812 } 2813 } 2814 2815 /** 2816 * Remove a restriction reason for disallowing carrier supported satellite plmn scan and attach 2817 * by modem. 2818 * 2819 * @param subId The subscription ID of the carrier. 2820 * @param reason Reason for disallowing satellite communication. 2821 * @param executor The executor on which the error code listener will be called. 2822 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 2823 * 2824 * @throws SecurityException if the caller doesn't have required permission. 2825 * @throws IllegalArgumentException if the subscription is invalid. 2826 * 2827 * @hide 2828 */ 2829 @SystemApi 2830 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) removeAttachRestrictionForCarrier(int subId, @SatelliteCommunicationRestrictionReason int reason, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)2831 public void removeAttachRestrictionForCarrier(int subId, 2832 @SatelliteCommunicationRestrictionReason int reason, 2833 @NonNull @CallbackExecutor Executor executor, 2834 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 2835 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 2836 throw new IllegalArgumentException("Invalid subscription ID"); 2837 } 2838 2839 try { 2840 ITelephony telephony = getITelephony(); 2841 if (telephony != null) { 2842 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 2843 @Override 2844 public void accept(int result) { 2845 executor.execute(() -> Binder.withCleanCallingIdentity( 2846 () -> resultListener.accept(result))); 2847 } 2848 }; 2849 telephony.removeAttachRestrictionForCarrier(subId, reason, errorCallback); 2850 } else { 2851 loge("removeAttachRestrictionForCarrier() invalid telephony"); 2852 executor.execute(() -> Binder.withCleanCallingIdentity( 2853 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 2854 } 2855 } catch (RemoteException ex) { 2856 loge("removeAttachRestrictionForCarrier() RemoteException:" + ex); 2857 executor.execute(() -> Binder.withCleanCallingIdentity( 2858 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 2859 } 2860 } 2861 2862 /** 2863 * Get reasons for disallowing satellite attach, as requested by 2864 * {@link #addAttachRestrictionForCarrier(int, int, Executor, Consumer)} 2865 * 2866 * @param subId The subscription ID of the carrier. 2867 * @return Set of reasons for disallowing satellite communication. 2868 * 2869 * @throws SecurityException if the caller doesn't have required permission. 2870 * @throws IllegalStateException if the Telephony process is not currently available. 2871 * @throws IllegalArgumentException if the subscription is invalid. 2872 * 2873 * @hide 2874 */ 2875 @SystemApi 2876 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2877 @SatelliteCommunicationRestrictionReason getAttachRestrictionReasonsForCarrier(int subId)2878 @NonNull public Set<Integer> getAttachRestrictionReasonsForCarrier(int subId) { 2879 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 2880 throw new IllegalArgumentException("Invalid subscription ID"); 2881 } 2882 2883 try { 2884 ITelephony telephony = getITelephony(); 2885 if (telephony != null) { 2886 int[] receivedArray = 2887 telephony.getAttachRestrictionReasonsForCarrier(subId); 2888 if (receivedArray.length == 0) { 2889 logd("receivedArray is empty, create empty set"); 2890 return new HashSet<>(); 2891 } else { 2892 return Arrays.stream(receivedArray).boxed().collect(Collectors.toSet()); 2893 } 2894 } else { 2895 throw new IllegalStateException("Telephony service is null."); 2896 } 2897 } catch (RemoteException ex) { 2898 loge("getAttachRestrictionReasonsForCarrier() RemoteException: " + ex); 2899 ex.rethrowAsRuntimeException(); 2900 } 2901 return new HashSet<>(); 2902 } 2903 2904 /** 2905 * Returns list of disallowed reasons of satellite. 2906 * 2907 * @return Integer array of disallowed reasons. 2908 * 2909 * @throws SecurityException if caller doesn't have required permission. 2910 * @throws IllegalStateException if Telephony process isn't available. 2911 * @hide 2912 */ 2913 @SystemApi 2914 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2915 @SatelliteDisallowedReason 2916 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 2917 @NonNull getSatelliteDisallowedReasons()2918 public int[] getSatelliteDisallowedReasons() { 2919 try { 2920 ITelephony telephony = getITelephony(); 2921 if (telephony != null) { 2922 return telephony.getSatelliteDisallowedReasons(); 2923 } else { 2924 throw new IllegalStateException("Telephony service is null."); 2925 } 2926 } catch (RemoteException ex) { 2927 loge("getSatelliteDisallowedReasons() RemoteException: " + ex); 2928 ex.rethrowAsRuntimeException(); 2929 } 2930 return new int[0]; 2931 } 2932 2933 /** 2934 * Registers for disallowed reasons change event from satellite service. 2935 * 2936 * @param executor The executor on which the callback will be called. 2937 * @param callback The callback to handle disallowed reasons changed event. 2938 * 2939 * @throws SecurityException if caller doesn't have required permission. 2940 * @throws IllegalStateException if Telephony process is not available. 2941 * @hide 2942 */ 2943 @SystemApi 2944 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2945 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) registerForSatelliteDisallowedReasonsChanged( @onNull @allbackExecutor Executor executor, @NonNull SatelliteDisallowedReasonsCallback callback)2946 public void registerForSatelliteDisallowedReasonsChanged( 2947 @NonNull @CallbackExecutor Executor executor, 2948 @NonNull SatelliteDisallowedReasonsCallback callback) { 2949 Objects.requireNonNull(executor); 2950 Objects.requireNonNull(callback); 2951 2952 try { 2953 ITelephony telephony = getITelephony(); 2954 if (telephony != null) { 2955 ISatelliteDisallowedReasonsCallback internalCallback = 2956 new ISatelliteDisallowedReasonsCallback.Stub() { 2957 @Override 2958 public void onSatelliteDisallowedReasonsChanged( 2959 int[] disallowedReasons) { 2960 executor.execute(() -> Binder.withCleanCallingIdentity( 2961 () -> callback.onSatelliteDisallowedReasonsChanged( 2962 disallowedReasons))); 2963 } 2964 }; 2965 telephony.registerForSatelliteDisallowedReasonsChanged(internalCallback); 2966 sSatelliteDisallowedReasonsCallbackMap.put(callback, internalCallback); 2967 } else { 2968 throw new IllegalStateException("Telephony service is null."); 2969 } 2970 } catch (RemoteException ex) { 2971 loge("registerForSatelliteDisallowedReasonsChanged() RemoteException" + ex); 2972 ex.rethrowAsRuntimeException(); 2973 } 2974 } 2975 2976 /** 2977 * Unregisters for disallowed reasons change event from satellite service. 2978 * 2979 * @param callback The callback that was passed to 2980 * {@link #registerForSatelliteDisallowedReasonsChanged( 2981 * Executor, SatelliteDisallowedReasonsCallback)} 2982 * 2983 * @throws SecurityException if caller doesn't have required permission. 2984 * @throws IllegalStateException if Telephony process is not available. 2985 * @hide 2986 */ 2987 @SystemApi 2988 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2989 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) unregisterForSatelliteDisallowedReasonsChanged( @onNull SatelliteDisallowedReasonsCallback callback)2990 public void unregisterForSatelliteDisallowedReasonsChanged( 2991 @NonNull SatelliteDisallowedReasonsCallback callback) { 2992 Objects.requireNonNull(callback); 2993 ISatelliteDisallowedReasonsCallback internalCallback = 2994 sSatelliteDisallowedReasonsCallbackMap.remove(callback); 2995 2996 try { 2997 ITelephony telephony = getITelephony(); 2998 if (telephony != null) { 2999 if (internalCallback != null) { 3000 telephony.unregisterForSatelliteDisallowedReasonsChanged(internalCallback); 3001 } else { 3002 loge("unregisterForSatelliteDisallowedReasonsChanged: No internal callback."); 3003 throw new IllegalArgumentException("callback is not valid"); 3004 } 3005 } else { 3006 throw new IllegalStateException("Telephony service is null."); 3007 } 3008 } catch (RemoteException ex) { 3009 loge("unregisterForSatelliteDisallowedReasonsChanged() RemoteException: " + ex); 3010 ex.rethrowAsRuntimeException(); 3011 } 3012 } 3013 3014 /** 3015 * Request to get the signal strength of the satellite connection. 3016 * 3017 * <p> 3018 * Note: This API is specifically designed for OEM enabled satellite connectivity only. 3019 * For satellite connectivity enabled using carrier roaming, please refer to 3020 * {@link TelephonyCallback.SignalStrengthsListener}, and 3021 * {@link TelephonyManager#registerTelephonyCallback(Executor, TelephonyCallback)}. 3022 * </p> 3023 * 3024 * @param executor The executor on which the callback will be called. 3025 * @param callback The callback object to which the result will be delivered. If the request is 3026 * successful, {@link OutcomeReceiver#onResult(Object)} will return an instance of 3027 * {@link NtnSignalStrength} with a value of {@link NtnSignalStrength.NtnSignalStrengthLevel} 3028 * The {@link NtnSignalStrength#NTN_SIGNAL_STRENGTH_NONE} will be returned if there is no 3029 * signal strength data available. 3030 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} will return a 3031 * {@link SatelliteException} with the {@link SatelliteResult}. 3032 * 3033 * @throws SecurityException if the caller doesn't have required permission. 3034 * 3035 * @hide 3036 */ 3037 @SystemApi 3038 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) requestNtnSignalStrength(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<NtnSignalStrength, SatelliteException> callback)3039 public void requestNtnSignalStrength(@NonNull @CallbackExecutor Executor executor, 3040 @NonNull OutcomeReceiver<NtnSignalStrength, SatelliteException> callback) { 3041 Objects.requireNonNull(executor); 3042 Objects.requireNonNull(callback); 3043 3044 try { 3045 ITelephony telephony = getITelephony(); 3046 if (telephony != null) { 3047 ResultReceiver receiver = new ResultReceiver(null) { 3048 @Override 3049 protected void onReceiveResult(int resultCode, Bundle resultData) { 3050 if (resultCode == SATELLITE_RESULT_SUCCESS) { 3051 if (resultData.containsKey(KEY_NTN_SIGNAL_STRENGTH)) { 3052 NtnSignalStrength ntnSignalStrength = 3053 resultData.getParcelable(KEY_NTN_SIGNAL_STRENGTH, 3054 NtnSignalStrength.class); 3055 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 3056 callback.onResult(ntnSignalStrength))); 3057 } else { 3058 loge("KEY_NTN_SIGNAL_STRENGTH does not exist."); 3059 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 3060 callback.onError(new SatelliteException( 3061 SATELLITE_RESULT_REQUEST_FAILED)))); 3062 } 3063 } else { 3064 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 3065 callback.onError(new SatelliteException(resultCode)))); 3066 } 3067 } 3068 }; 3069 telephony.requestNtnSignalStrength(receiver); 3070 } else { 3071 loge("requestNtnSignalStrength() invalid telephony"); 3072 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 3073 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 3074 } 3075 } catch (RemoteException ex) { 3076 loge("requestNtnSignalStrength() RemoteException: " + ex); 3077 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 3078 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 3079 } 3080 } 3081 3082 /** 3083 * Registers for NTN signal strength changed from satellite modem. 3084 * If the registration operation is not successful, a {@link SatelliteException} that contains 3085 * {@link SatelliteResult} will be thrown. 3086 * 3087 * <p> 3088 * Note: This API is specifically designed for OEM enabled satellite connectivity only. 3089 * For satellite connectivity enabled using carrier roaming, please refer to 3090 * {@link TelephonyCallback.SignalStrengthsListener}, and 3091 * {@link TelephonyManager#registerTelephonyCallback(Executor, TelephonyCallback)}. 3092 * </p> 3093 * 3094 * @param executor The executor on which the callback will be called. 3095 * @param callback The callback to handle the NTN signal strength changed event. 3096 * 3097 * @throws SecurityException if the caller doesn't have required permission. 3098 * @throws IllegalStateException if the Telephony process is not currently available. 3099 * 3100 * @hide 3101 */ 3102 @SystemApi 3103 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) registerForNtnSignalStrengthChanged(@onNull @allbackExecutor Executor executor, @NonNull NtnSignalStrengthCallback callback)3104 public void registerForNtnSignalStrengthChanged(@NonNull @CallbackExecutor Executor executor, 3105 @NonNull NtnSignalStrengthCallback callback) { 3106 Objects.requireNonNull(executor); 3107 Objects.requireNonNull(callback); 3108 3109 try { 3110 ITelephony telephony = getITelephony(); 3111 if (telephony != null) { 3112 INtnSignalStrengthCallback internalCallback = 3113 new INtnSignalStrengthCallback.Stub() { 3114 @Override 3115 public void onNtnSignalStrengthChanged( 3116 NtnSignalStrength ntnSignalStrength) { 3117 executor.execute(() -> Binder.withCleanCallingIdentity( 3118 () -> callback.onNtnSignalStrengthChanged( 3119 ntnSignalStrength))); 3120 } 3121 }; 3122 telephony.registerForNtnSignalStrengthChanged(internalCallback); 3123 sNtnSignalStrengthCallbackMap.put(callback, internalCallback); 3124 } else { 3125 throw new IllegalStateException("Telephony service is null."); 3126 } 3127 } catch (RemoteException ex) { 3128 loge("registerForNtnSignalStrengthChanged() RemoteException: " + ex); 3129 ex.rethrowAsRuntimeException(); 3130 } 3131 } 3132 3133 /** 3134 * Unregisters for NTN signal strength changed from satellite modem. 3135 * If callback was not registered before, the request will be ignored. 3136 * 3137 * <p> 3138 * Note: This API is specifically designed for OEM enabled satellite connectivity only. 3139 * For satellite connectivity enabled using carrier roaming, please refer to 3140 * {@link TelephonyManager#unregisterTelephonyCallback(TelephonyCallback)}.. 3141 * </p> 3142 * 3143 * @param callback The callback that was passed to. 3144 * {@link #registerForNtnSignalStrengthChanged(Executor, NtnSignalStrengthCallback)}. 3145 * 3146 * @throws SecurityException if the caller doesn't have required permission. 3147 * @throws IllegalArgumentException if the callback is not valid or has already been 3148 * unregistered. 3149 * @throws IllegalStateException if the Telephony process is not currently available. 3150 * 3151 * @hide 3152 */ 3153 @SystemApi 3154 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) unregisterForNtnSignalStrengthChanged(@onNull NtnSignalStrengthCallback callback)3155 public void unregisterForNtnSignalStrengthChanged(@NonNull NtnSignalStrengthCallback callback) { 3156 Objects.requireNonNull(callback); 3157 INtnSignalStrengthCallback internalCallback = 3158 sNtnSignalStrengthCallbackMap.remove(callback); 3159 3160 try { 3161 ITelephony telephony = getITelephony(); 3162 if (telephony != null) { 3163 if (internalCallback != null) { 3164 telephony.unregisterForNtnSignalStrengthChanged(internalCallback); 3165 } else { 3166 loge("unregisterForNtnSignalStrengthChanged: No internal callback."); 3167 throw new IllegalArgumentException("callback is not valid"); 3168 } 3169 } else { 3170 throw new IllegalStateException("Telephony service is null."); 3171 } 3172 } catch (RemoteException ex) { 3173 loge("unregisterForNtnSignalStrengthChanged() RemoteException: " + ex); 3174 ex.rethrowAsRuntimeException(); 3175 } 3176 } 3177 3178 /** 3179 * Registers for satellite capabilities change event from the satellite service. 3180 * 3181 * @param executor The executor on which the callback will be called. 3182 * @param callback The callback to handle the satellite capabilities changed event. 3183 * 3184 * @throws SecurityException if the caller doesn't have required permission. 3185 * @throws IllegalStateException if the Telephony process is not currently available. 3186 * 3187 * @hide 3188 */ 3189 @SystemApi 3190 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) registerForCapabilitiesChanged( @onNull @allbackExecutor Executor executor, @NonNull SatelliteCapabilitiesCallback callback)3191 @SatelliteResult public int registerForCapabilitiesChanged( 3192 @NonNull @CallbackExecutor Executor executor, 3193 @NonNull SatelliteCapabilitiesCallback callback) { 3194 Objects.requireNonNull(executor); 3195 Objects.requireNonNull(callback); 3196 3197 try { 3198 ITelephony telephony = getITelephony(); 3199 if (telephony != null) { 3200 ISatelliteCapabilitiesCallback internalCallback = 3201 new ISatelliteCapabilitiesCallback.Stub() { 3202 @Override 3203 public void onSatelliteCapabilitiesChanged( 3204 SatelliteCapabilities capabilities) { 3205 executor.execute(() -> Binder.withCleanCallingIdentity( 3206 () -> callback.onSatelliteCapabilitiesChanged( 3207 capabilities))); 3208 } 3209 }; 3210 sSatelliteCapabilitiesCallbackMap.put(callback, internalCallback); 3211 return telephony.registerForCapabilitiesChanged(internalCallback); 3212 } else { 3213 throw new IllegalStateException("Telephony service is null."); 3214 } 3215 } catch (RemoteException ex) { 3216 loge("registerForCapabilitiesChanged() RemoteException: " + ex); 3217 ex.rethrowAsRuntimeException(); 3218 } 3219 return SATELLITE_RESULT_REQUEST_FAILED; 3220 } 3221 3222 /** 3223 * Unregisters for satellite capabilities change event from the satellite service. 3224 * If callback was not registered before, the request will be ignored. 3225 * 3226 * @param callback The callback that was passed to. 3227 * {@link #registerForCapabilitiesChanged(Executor, SatelliteCapabilitiesCallback)}. 3228 * 3229 * @throws SecurityException if the caller doesn't have required permission. 3230 * @throws IllegalStateException if the Telephony process is not currently available. 3231 * 3232 * @hide 3233 */ 3234 @SystemApi 3235 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) unregisterForCapabilitiesChanged( @onNull SatelliteCapabilitiesCallback callback)3236 public void unregisterForCapabilitiesChanged( 3237 @NonNull SatelliteCapabilitiesCallback callback) { 3238 Objects.requireNonNull(callback); 3239 ISatelliteCapabilitiesCallback internalCallback = 3240 sSatelliteCapabilitiesCallbackMap.remove(callback); 3241 3242 try { 3243 ITelephony telephony = getITelephony(); 3244 if (telephony != null) { 3245 if (internalCallback != null) { 3246 telephony.unregisterForCapabilitiesChanged(internalCallback); 3247 } else { 3248 loge("unregisterForCapabilitiesChanged: No internal callback."); 3249 } 3250 } else { 3251 throw new IllegalStateException("Telephony service is null."); 3252 } 3253 } catch (RemoteException ex) { 3254 loge("unregisterForCapabilitiesChanged() RemoteException: " + ex); 3255 ex.rethrowAsRuntimeException(); 3256 } 3257 } 3258 3259 /** 3260 * Get all satellite PLMNs for which attach is enable for carrier. 3261 * 3262 * @param subId subId The subscription ID of the carrier. 3263 * 3264 * @return List of plmn for carrier satellite service. If no plmn is available, empty list will 3265 * be returned. 3266 * 3267 * @hide 3268 */ 3269 @SystemApi 3270 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) getSatellitePlmnsForCarrier(int subId)3271 @NonNull public List<String> getSatellitePlmnsForCarrier(int subId) { 3272 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 3273 throw new IllegalArgumentException("Invalid subscription ID"); 3274 } 3275 3276 try { 3277 ITelephony telephony = getITelephony(); 3278 if (telephony != null) { 3279 return telephony.getSatellitePlmnsForCarrier(subId); 3280 } else { 3281 throw new IllegalStateException("Telephony service is null."); 3282 } 3283 } catch (RemoteException ex) { 3284 loge("getSatellitePlmnsForCarrier() RemoteException: " + ex); 3285 ex.rethrowAsRuntimeException(); 3286 } 3287 return new ArrayList<>(); 3288 } 3289 3290 /** 3291 * Registers for the satellite supported state changed. 3292 * 3293 * @param executor The executor on which the callback will be called. 3294 * @param callback The callback to handle the satellite supoprted state changed event. 3295 * 3296 * @return The result of the operation. 3297 * 3298 * @throws SecurityException if the caller doesn't have required permission. 3299 * @throws IllegalStateException if the Telephony process is not currently available. 3300 * @hide 3301 */ 3302 @SystemApi 3303 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 3304 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) registerForSupportedStateChanged( @onNull @allbackExecutor Executor executor, @NonNull Consumer<Boolean> callback)3305 @SatelliteResult public int registerForSupportedStateChanged( 3306 @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { 3307 Objects.requireNonNull(executor); 3308 Objects.requireNonNull(callback); 3309 3310 try { 3311 ITelephony telephony = getITelephony(); 3312 if (telephony != null) { 3313 IBooleanConsumer internalCallback = new IBooleanConsumer.Stub() { 3314 @Override 3315 public void accept(boolean supported) { 3316 executor.execute(() -> Binder.withCleanCallingIdentity( 3317 () -> callback.accept(supported))); 3318 } 3319 }; 3320 sSatelliteSupportedStateCallbackMap.put(callback, internalCallback); 3321 return telephony.registerForSatelliteSupportedStateChanged( 3322 internalCallback); 3323 } else { 3324 throw new IllegalStateException("telephony service is null."); 3325 } 3326 } catch (RemoteException ex) { 3327 loge("registerForSupportedStateChanged() RemoteException: " + ex); 3328 ex.rethrowAsRuntimeException(); 3329 } 3330 return SATELLITE_RESULT_REQUEST_FAILED; 3331 } 3332 3333 /** 3334 * Unregisters for the satellite supported state changed. 3335 * If callback was not registered before, the request will be ignored. 3336 * 3337 * @param callback The callback that was passed to 3338 * {@link #registerForSupportedStateChanged(Executor, Consumer)} 3339 * 3340 * @throws SecurityException if the caller doesn't have required permission. 3341 * @throws IllegalStateException if the Telephony process is not currently available. 3342 * @hide 3343 */ 3344 @SystemApi 3345 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 3346 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) unregisterForSupportedStateChanged(@onNull Consumer<Boolean> callback)3347 public void unregisterForSupportedStateChanged(@NonNull Consumer<Boolean> callback) { 3348 Objects.requireNonNull(callback); 3349 IBooleanConsumer internalCallback = 3350 sSatelliteSupportedStateCallbackMap.remove(callback); 3351 3352 try { 3353 ITelephony telephony = getITelephony(); 3354 if (telephony != null) { 3355 if (internalCallback != null) { 3356 telephony.unregisterForSatelliteSupportedStateChanged(internalCallback); 3357 } else { 3358 loge("unregisterForSupportedStateChanged: No internal callback."); 3359 } 3360 } else { 3361 throw new IllegalStateException("telephony service is null."); 3362 } 3363 } catch (RemoteException ex) { 3364 loge("unregisterForSupportedStateChanged() RemoteException: " + ex); 3365 ex.rethrowAsRuntimeException(); 3366 } 3367 } 3368 3369 /** 3370 * Registers for the satellite communication access state changed event. 3371 * 3372 * @param executor The executor on which the callback will be called. 3373 * @param callback The callback to handle satellite communication access state changed event. 3374 * @return The {@link SatelliteResult} result of the operation. 3375 * @throws SecurityException if the caller doesn't have required permission. 3376 * @throws IllegalStateException if the Telephony process is not currently available. 3377 * @hide 3378 */ 3379 @SystemApi 3380 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) 3381 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 3382 @SatelliteResult registerForCommunicationAccessStateChanged( @onNull @allbackExecutor Executor executor, @NonNull SatelliteCommunicationAccessStateCallback callback)3383 public int registerForCommunicationAccessStateChanged( 3384 @NonNull @CallbackExecutor Executor executor, 3385 @NonNull SatelliteCommunicationAccessStateCallback callback) { 3386 Objects.requireNonNull(executor); 3387 Objects.requireNonNull(callback); 3388 3389 try { 3390 ITelephony telephony = getITelephony(); 3391 if (telephony != null) { 3392 ISatelliteCommunicationAccessStateCallback internalCallback = 3393 new ISatelliteCommunicationAccessStateCallback.Stub() { 3394 @Override 3395 public void onAccessAllowedStateChanged( 3396 boolean isAllowed) { 3397 executor.execute(() -> Binder.withCleanCallingIdentity( 3398 () -> callback.onAccessAllowedStateChanged( 3399 isAllowed))); 3400 } 3401 3402 @Override 3403 public void onAccessConfigurationChanged( 3404 @Nullable SatelliteAccessConfiguration 3405 satelliteAccessConfiguration) { 3406 executor.execute(() -> Binder.withCleanCallingIdentity( 3407 () -> callback.onAccessConfigurationChanged( 3408 satelliteAccessConfiguration))); 3409 } 3410 }; 3411 sSatelliteCommunicationAccessStateCallbackMap.put(callback, internalCallback); 3412 return telephony.registerForCommunicationAccessStateChanged( 3413 mSubId, internalCallback); 3414 } else { 3415 throw new IllegalStateException("telephony service is null."); 3416 } 3417 } catch (RemoteException ex) { 3418 loge("registerForCommunicationAccessStateChanged() RemoteException: " + ex); 3419 ex.rethrowAsRuntimeException(); 3420 } 3421 return SATELLITE_RESULT_REQUEST_FAILED; 3422 } 3423 3424 /** 3425 * Unregisters for the satellite communication access state changed event. 3426 * If callback was not registered before, the request will be ignored. 3427 * 3428 * @param callback The callback that was passed to 3429 * {@link #registerForCommunicationAccessStateChanged(Executor, 3430 * SatelliteCommunicationAccessStateCallback)} 3431 * @throws SecurityException if the caller doesn't have required permission. 3432 * @throws IllegalStateException if the Telephony process is not currently available. 3433 * @hide 3434 */ 3435 @SystemApi 3436 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 3437 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) unregisterForCommunicationAccessStateChanged( @onNull SatelliteCommunicationAccessStateCallback callback)3438 public void unregisterForCommunicationAccessStateChanged( 3439 @NonNull SatelliteCommunicationAccessStateCallback callback) { 3440 Objects.requireNonNull(callback); 3441 ISatelliteCommunicationAccessStateCallback internalCallback = 3442 sSatelliteCommunicationAccessStateCallbackMap.remove(callback); 3443 3444 try { 3445 ITelephony telephony = getITelephony(); 3446 if (telephony != null) { 3447 if (internalCallback != null) { 3448 telephony.unregisterForCommunicationAccessStateChanged(mSubId, 3449 internalCallback); 3450 } else { 3451 loge("unregisterForCommunicationAccessStateChanged: No internal callback."); 3452 } 3453 } else { 3454 throw new IllegalStateException("telephony service is null."); 3455 } 3456 } catch (RemoteException ex) { 3457 loge("unregisterForCommunicationAccessStateChanged() RemoteException: " + ex); 3458 ex.rethrowAsRuntimeException(); 3459 } 3460 } 3461 3462 /** 3463 * Request to get the {@link SatelliteSessionStats} of the satellite service. 3464 * 3465 * @param executor The executor on which the callback will be called. 3466 * @param callback The callback object to which the result will be delivered. 3467 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 3468 * will return the {@link SatelliteSessionStats} of the satellite service. 3469 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 3470 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 3471 * 3472 * @throws SecurityException if the caller doesn't have required permission. 3473 * @hide 3474 */ 3475 @RequiresPermission(allOf = {Manifest.permission.PACKAGE_USAGE_STATS, 3476 Manifest.permission.MODIFY_PHONE_STATE}) requestSessionStats(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<SatelliteSessionStats, SatelliteException> callback)3477 public void requestSessionStats(@NonNull @CallbackExecutor Executor executor, 3478 @NonNull OutcomeReceiver<SatelliteSessionStats, SatelliteException> callback) { 3479 Objects.requireNonNull(executor); 3480 Objects.requireNonNull(callback); 3481 3482 try { 3483 ITelephony telephony = getITelephony(); 3484 if (telephony != null) { 3485 ResultReceiver receiver = new ResultReceiver(null) { 3486 @Override 3487 protected void onReceiveResult(int resultCode, Bundle resultData) { 3488 if (resultCode == SATELLITE_RESULT_SUCCESS) { 3489 SatelliteSessionStats stats; 3490 if (resultData.containsKey(KEY_SESSION_STATS)) { 3491 stats = resultData.getParcelable(KEY_SESSION_STATS, 3492 SatelliteSessionStats.class); 3493 if (resultData.containsKey(KEY_SESSION_STATS_V2)) { 3494 SatelliteSessionStats stats1 = resultData.getParcelable( 3495 KEY_SESSION_STATS_V2, SatelliteSessionStats.class); 3496 if (stats != null && stats1 != null) { 3497 stats.setSatelliteSessionStats( 3498 stats1.getSatelliteSessionStats()); 3499 executor.execute(() -> Binder.withCleanCallingIdentity( 3500 () -> callback.onResult(stats))); 3501 return; 3502 } 3503 } else { 3504 loge("KEY_SESSION_STATS_V2 does not exist."); 3505 } 3506 } else { 3507 loge("KEY_SESSION_STATS does not exist."); 3508 } 3509 executor.execute(() -> Binder.withCleanCallingIdentity( 3510 () -> callback.onError(new SatelliteException( 3511 SATELLITE_RESULT_REQUEST_FAILED)))); 3512 3513 } else { 3514 executor.execute(() -> Binder.withCleanCallingIdentity( 3515 () -> callback.onError(new SatelliteException(resultCode)))); 3516 } 3517 } 3518 }; 3519 telephony.requestSatelliteSessionStats(mSubId, receiver); 3520 } else { 3521 loge("requestSessionStats() invalid telephony"); 3522 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 3523 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 3524 } 3525 } catch (RemoteException ex) { 3526 loge("requestSessionStats() RemoteException: " + ex); 3527 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 3528 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 3529 } 3530 } 3531 3532 /** 3533 * Request to get list of prioritized satellite subscriber ids to be used for provision. 3534 * 3535 * Satellite Gateway client will use these subscriber ids to register with satellite gateway 3536 * service which identify user subscription with unique subscriber ids. These subscriber ids 3537 * can be any unique value like iccid, imsi or msisdn which is decided based upon carrier 3538 * requirements. 3539 * 3540 * @param executor The executor on which the callback will be called. 3541 * @param callback The callback object to which the result will be delivered. 3542 * If successful, the callback returns a list of tokens sorted in ascending priority order index 3543 * 0 has the highest priority. Otherwise, it returns an error with a SatelliteException. 3544 * 3545 * @throws SecurityException if the caller doesn't have required permission. 3546 * @hide 3547 */ 3548 @SystemApi 3549 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 3550 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) requestSatelliteSubscriberProvisionStatus( @onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<List<SatelliteSubscriberProvisionStatus>, SatelliteException> callback)3551 public void requestSatelliteSubscriberProvisionStatus( 3552 @NonNull @CallbackExecutor Executor executor, 3553 @NonNull OutcomeReceiver<List<SatelliteSubscriberProvisionStatus>, 3554 SatelliteException> callback) { 3555 Objects.requireNonNull(executor); 3556 Objects.requireNonNull(callback); 3557 3558 try { 3559 ITelephony telephony = getITelephony(); 3560 if (telephony != null) { 3561 ResultReceiver receiver = new ResultReceiver(null) { 3562 @Override 3563 protected void onReceiveResult(int resultCode, Bundle resultData) { 3564 if (resultCode == SATELLITE_RESULT_SUCCESS) { 3565 if (resultData.containsKey(KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN)) { 3566 List<SatelliteSubscriberProvisionStatus> list = 3567 resultData.getParcelableArrayList( 3568 KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN, 3569 SatelliteSubscriberProvisionStatus.class); 3570 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 3571 callback.onResult(list))); 3572 } else { 3573 loge("KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN does not exist."); 3574 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 3575 callback.onError(new SatelliteException( 3576 SATELLITE_RESULT_REQUEST_FAILED)))); 3577 } 3578 } else { 3579 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 3580 callback.onError(new SatelliteException(resultCode)))); 3581 } 3582 } 3583 }; 3584 telephony.requestSatelliteSubscriberProvisionStatus(receiver); 3585 } else { 3586 loge("requestSatelliteSubscriberProvisionStatus() invalid telephony"); 3587 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 3588 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 3589 } 3590 } catch (RemoteException ex) { 3591 loge("requestSatelliteSubscriberProvisionStatus() RemoteException: " + ex); 3592 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 3593 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 3594 } 3595 } 3596 3597 /** 3598 * Request to get the display name of satellite feature in the UI. 3599 * 3600 * @param executor The executor on which the callback will be called. 3601 * @param callback The callback object to which the result will be delivered. 3602 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 3603 * will return display name of the satellite feature in string format. Default 3604 * display name is "Satellite". If the request is not successful, 3605 * {@link OutcomeReceiver#onError(Throwable)} will return an error with 3606 * a SatelliteException. 3607 * 3608 * @throws SecurityException if the caller doesn't have required permission. 3609 * @throws IllegalStateException if the Telephony process is not currently available. 3610 * @hide 3611 */ 3612 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) requestSatelliteDisplayName( @onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<CharSequence, SatelliteException> callback)3613 public void requestSatelliteDisplayName( 3614 @NonNull @CallbackExecutor Executor executor, 3615 @NonNull OutcomeReceiver<CharSequence, SatelliteException> callback) { 3616 Objects.requireNonNull(executor); 3617 Objects.requireNonNull(callback); 3618 3619 try { 3620 ITelephony telephony = getITelephony(); 3621 if (telephony != null) { 3622 ResultReceiver receiver = new ResultReceiver(null) { 3623 @Override 3624 protected void onReceiveResult(int resultCode, Bundle resultData) { 3625 if (resultCode == SATELLITE_RESULT_SUCCESS) { 3626 if (resultData.containsKey(KEY_SATELLITE_DISPLAY_NAME)) { 3627 CharSequence satelliteDisplayName = 3628 resultData.getString(KEY_SATELLITE_DISPLAY_NAME); 3629 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 3630 callback.onResult(satelliteDisplayName))); 3631 } else { 3632 loge("KEY_SATELLITE_DISPLAY_NAME does not exist."); 3633 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 3634 callback.onError(new SatelliteException( 3635 SATELLITE_RESULT_REQUEST_FAILED)))); 3636 } 3637 } else { 3638 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 3639 callback.onError(new SatelliteException(resultCode)))); 3640 } 3641 } 3642 }; 3643 telephony.requestSatelliteDisplayName(receiver); 3644 } else { 3645 loge("requestSatelliteDisplayName() invalid telephony"); 3646 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 3647 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 3648 } 3649 } catch (RemoteException ex) { 3650 loge("requestSatelliteDisplayName() RemoteException: " + ex); 3651 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 3652 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 3653 } 3654 } 3655 3656 /** 3657 * Deliver the list of provisioned satellite subscriber infos. 3658 * 3659 * @param list The list of provisioned satellite subscriber infos. 3660 * @param executor The executor on which the callback will be called. 3661 * @param callback The callback object to which the result will be delivered. 3662 * If the request is successful, {@link OutcomeReceiver#onResult} 3663 * will be called. 3664 * If the request is not successful, 3665 * {@link OutcomeReceiver#onError(Throwable)} will return an error with 3666 * a SatelliteException. 3667 * 3668 * @throws SecurityException if the caller doesn't have required permission. 3669 * @hide 3670 */ 3671 @SystemApi 3672 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 3673 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) provisionSatellite(@onNull List<SatelliteSubscriberInfo> list, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Void, SatelliteException> callback)3674 public void provisionSatellite(@NonNull List<SatelliteSubscriberInfo> list, 3675 @NonNull @CallbackExecutor Executor executor, 3676 @NonNull OutcomeReceiver<Void, SatelliteException> callback) { 3677 Objects.requireNonNull(executor); 3678 Objects.requireNonNull(callback); 3679 3680 try { 3681 ITelephony telephony = getITelephony(); 3682 if (telephony != null) { 3683 ResultReceiver receiver = new ResultReceiver(null) { 3684 @Override 3685 protected void onReceiveResult(int resultCode, Bundle resultData) { 3686 if (resultCode == SATELLITE_RESULT_SUCCESS) { 3687 if (resultData.containsKey(KEY_PROVISION_SATELLITE_TOKENS)) { 3688 boolean isUpdated = 3689 resultData.getBoolean(KEY_PROVISION_SATELLITE_TOKENS); 3690 executor.execute(() -> Binder.withCleanCallingIdentity( 3691 () -> callback.onResult(null))); 3692 } else { 3693 loge("KEY_REQUEST_PROVISION_TOKENS does not exist."); 3694 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 3695 callback.onError(new SatelliteException( 3696 SATELLITE_RESULT_REQUEST_FAILED)))); 3697 } 3698 } else { 3699 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 3700 callback.onError(new SatelliteException(resultCode)))); 3701 } 3702 } 3703 }; 3704 telephony.provisionSatellite(list, receiver); 3705 } else { 3706 loge("provisionSatellite() invalid telephony"); 3707 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 3708 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 3709 } 3710 } catch (RemoteException ex) { 3711 loge("provisionSatellite() RemoteException: " + ex); 3712 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 3713 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 3714 } 3715 } 3716 3717 /** 3718 * Deliver the list of deprovisioned satellite subscriber infos. 3719 * 3720 * @param list The list of deprovisioned satellite subscriber infos. 3721 * @param executor The executor on which the callback will be called. 3722 * @param callback The callback object to which the result will be delivered. 3723 * If the request is successful, {@link OutcomeReceiver#onResult} 3724 * will be called. 3725 * If the request is not successful, 3726 * {@link OutcomeReceiver#onError(Throwable)} will return an error with 3727 * a SatelliteException. 3728 * 3729 * @throws SecurityException if the caller doesn't have required permission. 3730 * @hide 3731 */ 3732 @SystemApi 3733 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 3734 @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) deprovisionSatellite(@onNull List<SatelliteSubscriberInfo> list, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Void, SatelliteException> callback)3735 public void deprovisionSatellite(@NonNull List<SatelliteSubscriberInfo> list, 3736 @NonNull @CallbackExecutor Executor executor, 3737 @NonNull OutcomeReceiver<Void, SatelliteException> callback) { 3738 Objects.requireNonNull(executor); 3739 Objects.requireNonNull(callback); 3740 3741 try { 3742 ITelephony telephony = getITelephony(); 3743 if (telephony != null) { 3744 ResultReceiver receiver = new ResultReceiver(null) { 3745 @Override 3746 protected void onReceiveResult(int resultCode, Bundle resultData) { 3747 if (resultCode == SATELLITE_RESULT_SUCCESS) { 3748 if (resultData.containsKey(KEY_DEPROVISION_SATELLITE_TOKENS)) { 3749 boolean isUpdated = 3750 resultData.getBoolean(KEY_DEPROVISION_SATELLITE_TOKENS); 3751 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 3752 callback.onResult(null))); 3753 } else { 3754 loge("KEY_DEPROVISION_SATELLITE_TOKENS does not exist."); 3755 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 3756 callback.onError(new SatelliteException( 3757 SATELLITE_RESULT_REQUEST_FAILED)))); 3758 } 3759 } else { 3760 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 3761 callback.onError(new SatelliteException(resultCode)))); 3762 } 3763 } 3764 }; 3765 telephony.deprovisionSatellite(list, receiver); 3766 } else { 3767 loge("deprovisionSatellite() invalid telephony"); 3768 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 3769 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 3770 } 3771 } catch (RemoteException ex) { 3772 loge("deprovisionSatellite() RemoteException: " + ex); 3773 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 3774 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 3775 } 3776 } 3777 3778 /** 3779 * Inform whether application supports NTN SMS in satellite mode. 3780 * 3781 * This method is used by default messaging application to inform framework whether it supports 3782 * NTN SMS or not. 3783 * 3784 * Invoking this API will internally result in triggering 3785 * {@link android.telephony.TelephonyCallback.CarrierRoamingNtnModeListener 3786 * #onCarrierRoamingNtnAvailableServicesChanged(List)} and 3787 * {@link android.telephony.TelephonyCallback.CarrierRoamingNtnModeListener 3788 * #onCarrierRoamingNtnEligibleStateChanged(boolean)} callbacks. 3789 * 3790 * @param ntnSmsSupported {@code true} If application supports NTN SMS, else {@code false}. 3791 * 3792 * @throws SecurityException if the caller doesn't have required permission. 3793 * @throws IllegalStateException if the Telephony process is not currently available. 3794 * @hide 3795 */ 3796 @RequiresPermission(allOf = {Manifest.permission.SATELLITE_COMMUNICATION, 3797 Manifest.permission.SEND_SMS}) setNtnSmsSupported(boolean ntnSmsSupported)3798 public void setNtnSmsSupported(boolean ntnSmsSupported) { 3799 try { 3800 ITelephony telephony = getITelephony(); 3801 if (telephony != null) { 3802 telephony.setNtnSmsSupported(ntnSmsSupported); 3803 } else { 3804 throw new IllegalStateException("telephony service is null."); 3805 } 3806 } catch (RemoteException ex) { 3807 loge("setNtnSmsSupported() RemoteException:" + ex); 3808 ex.rethrowAsRuntimeException(); 3809 } 3810 } 3811 3812 /** 3813 * Get list of application packages name that are optimized for low bandwidth satellite data. 3814 * 3815 * @return List of application packages name with data optimized network property. 3816 * 3817 * {@link #PROPERTY_SATELLITE_DATA_OPTIMIZED} 3818 * 3819 * @hide 3820 */ 3821 @SystemApi 3822 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 3823 @FlaggedApi(Flags.FLAG_SATELLITE_25Q4_APIS) getSatelliteDataOptimizedApps()3824 public @NonNull List<String> getSatelliteDataOptimizedApps() { 3825 List<String> appsNames = new ArrayList<>(); 3826 try { 3827 ITelephony telephony = getITelephony(); 3828 if (telephony != null) { 3829 appsNames = telephony.getSatelliteDataOptimizedApps(); 3830 } else { 3831 throw new IllegalStateException("telephony service is null."); 3832 } 3833 } catch (RemoteException ex) { 3834 loge("getSatelliteDataOptimizedApps() RemoteException:" + ex); 3835 ex.rethrowAsRuntimeException(); 3836 } 3837 3838 return appsNames; 3839 } 3840 3841 /** 3842 * Method to return the current satellite data service policy supported mode for the 3843 * subscriptionId based on carrier config. 3844 * 3845 * @param subId current subscription id. 3846 * 3847 * @return Supported modes {@link SatelliteDataSupportMode} 3848 * @throws IllegalArgumentException if the subscription is invalid. 3849 * 3850 * @hide 3851 */ 3852 @SystemApi 3853 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 3854 @FlaggedApi(Flags.FLAG_SATELLITE_25Q4_APIS) 3855 @SatelliteDataSupportMode getSatelliteDataSupportMode(int subId)3856 public int getSatelliteDataSupportMode(int subId) { 3857 int satelliteMode = SATELLITE_DATA_SUPPORT_UNKNOWN; 3858 3859 try { 3860 ITelephony telephony = getITelephony(); 3861 if (telephony != null) { 3862 satelliteMode = telephony.getSatelliteDataSupportMode(subId); 3863 } else { 3864 throw new IllegalStateException("telephony service is null."); 3865 } 3866 } catch (RemoteException ex) { 3867 loge("getSatelliteDataSupportMode() RemoteException:" + ex); 3868 ex.rethrowAsRuntimeException(); 3869 } 3870 3871 return satelliteMode; 3872 } 3873 3874 @Nullable getITelephony()3875 private static ITelephony getITelephony() { 3876 ITelephony binder = ITelephony.Stub.asInterface(TelephonyFrameworkInitializer 3877 .getTelephonyServiceManager() 3878 .getTelephonyServiceRegisterer() 3879 .get()); 3880 return binder; 3881 } 3882 logd(@onNull String log)3883 private static void logd(@NonNull String log) { 3884 Rlog.d(TAG, log); 3885 } 3886 loge(@onNull String log)3887 private static void loge(@NonNull String log) { 3888 Rlog.e(TAG, log); 3889 } 3890 } 3891