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.IntDef; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.RequiresFeature; 26 import android.annotation.RequiresPermission; 27 import android.annotation.SystemApi; 28 import android.content.Context; 29 import android.content.pm.PackageManager; 30 import android.os.Binder; 31 import android.os.Bundle; 32 import android.os.CancellationSignal; 33 import android.os.ICancellationSignal; 34 import android.os.OutcomeReceiver; 35 import android.os.RemoteException; 36 import android.os.ResultReceiver; 37 import android.telephony.SubscriptionManager; 38 import android.telephony.TelephonyCallback; 39 import android.telephony.TelephonyFrameworkInitializer; 40 import android.telephony.TelephonyManager; 41 42 import com.android.internal.telephony.IIntegerConsumer; 43 import com.android.internal.telephony.ITelephony; 44 import com.android.internal.telephony.IVoidConsumer; 45 import com.android.internal.telephony.flags.Flags; 46 import com.android.telephony.Rlog; 47 48 import java.lang.annotation.Retention; 49 import java.lang.annotation.RetentionPolicy; 50 import java.time.Duration; 51 import java.util.ArrayList; 52 import java.util.Arrays; 53 import java.util.HashSet; 54 import java.util.List; 55 import java.util.Objects; 56 import java.util.Set; 57 import java.util.concurrent.ConcurrentHashMap; 58 import java.util.concurrent.Executor; 59 import java.util.function.Consumer; 60 import java.util.stream.Collectors; 61 62 /** 63 * Manages satellite operations such as provisioning, pointing, messaging, location sharing, etc. 64 * To get the object, call {@link Context#getSystemService(String)}. 65 * 66 * @hide 67 */ 68 @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SATELLITE) 69 @SystemApi 70 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 71 public final class SatelliteManager { 72 private static final String TAG = "SatelliteManager"; 73 74 private static final ConcurrentHashMap<SatelliteDatagramCallback, ISatelliteDatagramCallback> 75 sSatelliteDatagramCallbackMap = new ConcurrentHashMap<>(); 76 private static final ConcurrentHashMap<SatelliteProvisionStateCallback, 77 ISatelliteProvisionStateCallback> sSatelliteProvisionStateCallbackMap = 78 new ConcurrentHashMap<>(); 79 private static final ConcurrentHashMap<SatelliteModemStateCallback, 80 ISatelliteModemStateCallback> 81 sSatelliteModemStateCallbackMap = new ConcurrentHashMap<>(); 82 private static final ConcurrentHashMap<SatelliteTransmissionUpdateCallback, 83 ISatelliteTransmissionUpdateCallback> sSatelliteTransmissionUpdateCallbackMap = 84 new ConcurrentHashMap<>(); 85 private static final ConcurrentHashMap<NtnSignalStrengthCallback, INtnSignalStrengthCallback> 86 sNtnSignalStrengthCallbackMap = new ConcurrentHashMap<>(); 87 private static final ConcurrentHashMap<SatelliteCapabilitiesCallback, 88 ISatelliteCapabilitiesCallback> 89 sSatelliteCapabilitiesCallbackMap = new ConcurrentHashMap<>(); 90 private static final ConcurrentHashMap<SatelliteSupportedStateCallback, 91 ISatelliteSupportedStateCallback> sSatelliteSupportedStateCallbackMap = 92 new ConcurrentHashMap<>(); 93 94 private static final ConcurrentHashMap<SatelliteCommunicationAllowedStateCallback, 95 ISatelliteCommunicationAllowedStateCallback> 96 sSatelliteCommunicationAllowedStateCallbackMap = 97 new ConcurrentHashMap<>(); 98 99 private final int mSubId; 100 101 /** 102 * Context this SatelliteManager is for. 103 */ 104 @Nullable private final Context mContext; 105 106 /** 107 * Create an instance of the SatelliteManager. 108 * 109 * @param context The context the SatelliteManager belongs to. 110 * @hide 111 */ SatelliteManager(@ullable Context context)112 public SatelliteManager(@Nullable Context context) { 113 this(context, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 114 } 115 116 /** 117 * Create an instance of the SatelliteManager associated with a particular subscription. 118 * 119 * @param context The context the SatelliteManager belongs to. 120 * @param subId The subscription ID associated with the SatelliteManager. 121 */ SatelliteManager(@ullable Context context, int subId)122 private SatelliteManager(@Nullable Context context, int subId) { 123 mContext = context; 124 mSubId = subId; 125 } 126 127 /** 128 * Exception from the satellite service containing the {@link SatelliteResult} error code. 129 */ 130 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 131 public static class SatelliteException extends Exception { 132 @SatelliteResult private final int mErrorCode; 133 134 /** 135 * Create a SatelliteException with a given error code. 136 * 137 * @param errorCode The {@link SatelliteResult}. 138 */ 139 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) SatelliteException(@atelliteResult int errorCode)140 public SatelliteException(@SatelliteResult int errorCode) { 141 mErrorCode = errorCode; 142 } 143 144 /** 145 * Get the error code returned from the satellite service. 146 * 147 * @return The {@link SatelliteResult}. 148 */ 149 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) getErrorCode()150 @SatelliteResult public int getErrorCode() { 151 return mErrorCode; 152 } 153 } 154 155 /** 156 * Bundle key to get the response from 157 * {@link #requestIsEnabled(Executor, OutcomeReceiver)}. 158 * @hide 159 */ 160 161 public static final String KEY_SATELLITE_ENABLED = "satellite_enabled"; 162 163 /** 164 * Bundle key to get the response from 165 * {@link #requestIsDemoModeEnabled(Executor, OutcomeReceiver)}. 166 * @hide 167 */ 168 169 public static final String KEY_DEMO_MODE_ENABLED = "demo_mode_enabled"; 170 171 /** 172 * Bundle key to get the response from 173 * {@link #requestIsEmergencyModeEnabled(Executor, OutcomeReceiver)}. 174 * @hide 175 */ 176 public static final String KEY_EMERGENCY_MODE_ENABLED = "emergency_mode_enabled"; 177 178 /** 179 * Bundle key to get the response from 180 * {@link #requestIsSupported(Executor, OutcomeReceiver)}. 181 * @hide 182 */ 183 184 public static final String KEY_SATELLITE_SUPPORTED = "satellite_supported"; 185 186 /** 187 * Bundle key to get the response from 188 * {@link #requestCapabilities(Executor, OutcomeReceiver)}. 189 * @hide 190 */ 191 192 public static final String KEY_SATELLITE_CAPABILITIES = "satellite_capabilities"; 193 194 /** 195 * Bundle key to get the response from 196 * {@link #requestSessionStats(Executor, OutcomeReceiver)}. 197 * @hide 198 */ 199 200 public static final String KEY_SESSION_STATS = "session_stats"; 201 202 /** 203 * Bundle key to get the response from 204 * {@link #requestIsProvisioned(Executor, OutcomeReceiver)}. 205 * @hide 206 */ 207 208 public static final String KEY_SATELLITE_PROVISIONED = "satellite_provisioned"; 209 210 /** 211 * Bundle key to get the response from 212 * {@link #requestIsCommunicationAllowedForCurrentLocation(Executor, OutcomeReceiver)}. 213 * @hide 214 */ 215 216 public static final String KEY_SATELLITE_COMMUNICATION_ALLOWED = 217 "satellite_communication_allowed"; 218 219 /** 220 * Bundle key to get the response from 221 * {@link #requestTimeForNextSatelliteVisibility(Executor, OutcomeReceiver)}. 222 * @hide 223 */ 224 225 public static final String KEY_SATELLITE_NEXT_VISIBILITY = "satellite_next_visibility"; 226 227 /** 228 * Bundle key to get the response from 229 * {@link #requestNtnSignalStrength(Executor, OutcomeReceiver)}. 230 * @hide 231 */ 232 233 public static final String KEY_NTN_SIGNAL_STRENGTH = "ntn_signal_strength"; 234 235 /** 236 * The request was successfully processed. 237 */ 238 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 239 public static final int SATELLITE_RESULT_SUCCESS = 0; 240 /** 241 * A generic error which should be used only when other specific errors cannot be used. 242 */ 243 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 244 public static final int SATELLITE_RESULT_ERROR = 1; 245 /** 246 * Error received from the satellite server. 247 */ 248 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 249 public static final int SATELLITE_RESULT_SERVER_ERROR = 2; 250 /** 251 * Error received from the vendor service. This generic error code should be used 252 * only when the error cannot be mapped to other specific service error codes. 253 */ 254 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 255 public static final int SATELLITE_RESULT_SERVICE_ERROR = 3; 256 /** 257 * Error received from satellite modem. This generic error code should be used only when 258 * the error cannot be mapped to other specific modem error codes. 259 */ 260 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 261 public static final int SATELLITE_RESULT_MODEM_ERROR = 4; 262 /** 263 * Error received from the satellite network. This generic error code should be used only when 264 * the error cannot be mapped to other specific network error codes. 265 */ 266 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 267 public static final int SATELLITE_RESULT_NETWORK_ERROR = 5; 268 /** 269 * Telephony is not in a valid state to receive requests from clients. 270 */ 271 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 272 public static final int SATELLITE_RESULT_INVALID_TELEPHONY_STATE = 6; 273 /** 274 * Satellite modem is not in a valid state to receive requests from clients. 275 */ 276 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 277 public static final int SATELLITE_RESULT_INVALID_MODEM_STATE = 7; 278 /** 279 * Either vendor service, or modem, or Telephony framework has received a request with 280 * invalid arguments from its clients. 281 */ 282 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 283 public static final int SATELLITE_RESULT_INVALID_ARGUMENTS = 8; 284 /** 285 * Telephony framework failed to send a request or receive a response from the vendor service 286 * or satellite modem due to internal error. 287 */ 288 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 289 public static final int SATELLITE_RESULT_REQUEST_FAILED = 9; 290 /** 291 * Radio did not start or is resetting. 292 */ 293 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 294 public static final int SATELLITE_RESULT_RADIO_NOT_AVAILABLE = 10; 295 /** 296 * The request is not supported by either the satellite modem or the network. 297 */ 298 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 299 public static final int SATELLITE_RESULT_REQUEST_NOT_SUPPORTED = 11; 300 /** 301 * Satellite modem or network has no resources available to handle requests from clients. 302 */ 303 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 304 public static final int SATELLITE_RESULT_NO_RESOURCES = 12; 305 /** 306 * Satellite service is not provisioned yet. 307 */ 308 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 309 public static final int SATELLITE_RESULT_SERVICE_NOT_PROVISIONED = 13; 310 /** 311 * Satellite service provision is already in progress. 312 */ 313 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 314 public static final int SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS = 14; 315 /** 316 * The ongoing request was aborted by either the satellite modem or the network. 317 * This error is also returned when framework decides to abort current send request as one 318 * of the previous send request failed. 319 */ 320 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 321 public static final int SATELLITE_RESULT_REQUEST_ABORTED = 15; 322 /** 323 * The device/subscriber is barred from accessing the satellite service. 324 */ 325 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 326 public static final int SATELLITE_RESULT_ACCESS_BARRED = 16; 327 /** 328 * Satellite modem timeout to receive ACK or response from the satellite network after 329 * sending a request to the network. 330 */ 331 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 332 public static final int SATELLITE_RESULT_NETWORK_TIMEOUT = 17; 333 /** 334 * Satellite network is not reachable from the modem. 335 */ 336 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 337 public static final int SATELLITE_RESULT_NOT_REACHABLE = 18; 338 /** 339 * The device/subscriber is not authorized to register with the satellite service provider. 340 */ 341 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 342 public static final int SATELLITE_RESULT_NOT_AUTHORIZED = 19; 343 /** 344 * The device does not support satellite. 345 */ 346 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 347 public static final int SATELLITE_RESULT_NOT_SUPPORTED = 20; 348 349 /** 350 * The current request is already in-progress. 351 */ 352 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 353 public static final int SATELLITE_RESULT_REQUEST_IN_PROGRESS = 21; 354 355 /** 356 * Satellite modem is currently busy due to which current request cannot be processed. 357 */ 358 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 359 public static final int SATELLITE_RESULT_MODEM_BUSY = 22; 360 361 /** 362 * Telephony process is not currently available or satellite is not supported. 363 */ 364 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 365 public static final int SATELLITE_RESULT_ILLEGAL_STATE = 23; 366 367 /** 368 * Telephony framework timeout to receive ACK or response from the satellite modem after 369 * sending a request to the modem. 370 */ 371 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 372 public static final int SATELLITE_RESULT_MODEM_TIMEOUT = 24; 373 374 /** 375 * Telephony framework needs to access the current location of the device to perform the 376 * request. However, location in the settings is disabled by users. 377 * 378 * @hide 379 */ 380 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 381 public static final int SATELLITE_RESULT_LOCATION_DISABLED = 25; 382 383 /** 384 * Telephony framework needs to access the current location of the device to perform the 385 * request. However, Telephony fails to fetch the current location from location service. 386 * 387 * @hide 388 */ 389 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 390 public static final int SATELLITE_RESULT_LOCATION_NOT_AVAILABLE = 26; 391 392 /** @hide */ 393 @IntDef(prefix = {"SATELLITE_RESULT_"}, value = { 394 SATELLITE_RESULT_SUCCESS, 395 SATELLITE_RESULT_ERROR, 396 SATELLITE_RESULT_SERVER_ERROR, 397 SATELLITE_RESULT_SERVICE_ERROR, 398 SATELLITE_RESULT_MODEM_ERROR, 399 SATELLITE_RESULT_NETWORK_ERROR, 400 SATELLITE_RESULT_INVALID_TELEPHONY_STATE, 401 SATELLITE_RESULT_INVALID_MODEM_STATE, 402 SATELLITE_RESULT_INVALID_ARGUMENTS, 403 SATELLITE_RESULT_REQUEST_FAILED, 404 SATELLITE_RESULT_RADIO_NOT_AVAILABLE, 405 SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, 406 SATELLITE_RESULT_NO_RESOURCES, 407 SATELLITE_RESULT_SERVICE_NOT_PROVISIONED, 408 SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS, 409 SATELLITE_RESULT_REQUEST_ABORTED, 410 SATELLITE_RESULT_ACCESS_BARRED, 411 SATELLITE_RESULT_NETWORK_TIMEOUT, 412 SATELLITE_RESULT_NOT_REACHABLE, 413 SATELLITE_RESULT_NOT_AUTHORIZED, 414 SATELLITE_RESULT_NOT_SUPPORTED, 415 SATELLITE_RESULT_REQUEST_IN_PROGRESS, 416 SATELLITE_RESULT_MODEM_BUSY, 417 SATELLITE_RESULT_ILLEGAL_STATE, 418 SATELLITE_RESULT_MODEM_TIMEOUT, 419 SATELLITE_RESULT_LOCATION_DISABLED, 420 SATELLITE_RESULT_LOCATION_NOT_AVAILABLE 421 }) 422 @Retention(RetentionPolicy.SOURCE) 423 public @interface SatelliteResult {} 424 425 /** 426 * Unknown Non-Terrestrial radio technology. This generic radio technology should be used 427 * only when the radio technology cannot be mapped to other specific radio technologies. 428 */ 429 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 430 public static final int NT_RADIO_TECHNOLOGY_UNKNOWN = 0; 431 /** 432 * 3GPP NB-IoT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology. 433 */ 434 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 435 public static final int NT_RADIO_TECHNOLOGY_NB_IOT_NTN = 1; 436 /** 437 * 3GPP 5G NR over Non-Terrestrial-Networks technology. 438 */ 439 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 440 public static final int NT_RADIO_TECHNOLOGY_NR_NTN = 2; 441 /** 442 * 3GPP eMTC (enhanced Machine-Type Communication) over Non-Terrestrial-Networks technology. 443 */ 444 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 445 public static final int NT_RADIO_TECHNOLOGY_EMTC_NTN = 3; 446 /** 447 * Proprietary technology. 448 */ 449 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 450 public static final int NT_RADIO_TECHNOLOGY_PROPRIETARY = 4; 451 452 /** @hide */ 453 @IntDef(prefix = "NT_RADIO_TECHNOLOGY_", value = { 454 NT_RADIO_TECHNOLOGY_UNKNOWN, 455 NT_RADIO_TECHNOLOGY_NB_IOT_NTN, 456 NT_RADIO_TECHNOLOGY_NR_NTN, 457 NT_RADIO_TECHNOLOGY_EMTC_NTN, 458 NT_RADIO_TECHNOLOGY_PROPRIETARY 459 }) 460 @Retention(RetentionPolicy.SOURCE) 461 public @interface NTRadioTechnology {} 462 463 /** Suggested device hold position is unknown. */ 464 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 465 public static final int DEVICE_HOLD_POSITION_UNKNOWN = 0; 466 /** User is suggested to hold the device in portrait mode. */ 467 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 468 public static final int DEVICE_HOLD_POSITION_PORTRAIT = 1; 469 /** User is suggested to hold the device in landscape mode with left hand. */ 470 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 471 public static final int DEVICE_HOLD_POSITION_LANDSCAPE_LEFT = 2; 472 /** User is suggested to hold the device in landscape mode with right hand. */ 473 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 474 public static final int DEVICE_HOLD_POSITION_LANDSCAPE_RIGHT = 3; 475 476 /** @hide */ 477 @IntDef(prefix = {"DEVICE_HOLD_POSITION_"}, value = { 478 DEVICE_HOLD_POSITION_UNKNOWN, 479 DEVICE_HOLD_POSITION_PORTRAIT, 480 DEVICE_HOLD_POSITION_LANDSCAPE_LEFT, 481 DEVICE_HOLD_POSITION_LANDSCAPE_RIGHT 482 }) 483 @Retention(RetentionPolicy.SOURCE) 484 public @interface DeviceHoldPosition {} 485 486 /** Display mode is unknown. */ 487 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 488 public static final int DISPLAY_MODE_UNKNOWN = 0; 489 /** Display mode of the device used for satellite communication for non-foldable phones. */ 490 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 491 public static final int DISPLAY_MODE_FIXED = 1; 492 /** Display mode of the device used for satellite communication for foldabale phones when the 493 * device is opened. */ 494 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 495 public static final int DISPLAY_MODE_OPENED = 2; 496 /** Display mode of the device used for satellite communication for foldabable phones when the 497 * device is closed. */ 498 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 499 public static final int DISPLAY_MODE_CLOSED = 3; 500 501 /** @hide */ 502 @IntDef(prefix = {"ANTENNA_POSITION_"}, value = { 503 DISPLAY_MODE_UNKNOWN, 504 DISPLAY_MODE_FIXED, 505 DISPLAY_MODE_OPENED, 506 DISPLAY_MODE_CLOSED 507 }) 508 @Retention(RetentionPolicy.SOURCE) 509 public @interface DisplayMode {} 510 511 /** 512 * The emergency call is handed over to oem-enabled satellite SOS messaging. SOS messages are 513 * sent to SOS providers, which will then forward the messages to emergency providers. 514 */ 515 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 516 public static final int EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS = 1; 517 /** 518 * The emergency call is handed over to carrier-enabled satellite T911 messaging. T911 messages 519 * are sent directly to local emergency providers. 520 */ 521 @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) 522 public static final int EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911 = 2; 523 524 /** 525 * Request to enable or disable the satellite modem and demo mode. 526 * If satellite modem and cellular modem cannot work concurrently, 527 * then this will disable the cellular modem if satellite modem is enabled, 528 * and will re-enable the cellular modem if satellite modem is disabled. 529 * 530 * Demo mode is created to simulate the experience of sending and receiving messages over 531 * satellite. If user enters demo mode, a request should be sent to framework to enable 532 * satellite with enableDemoMode set to {code true}. Once satellite is enabled and device is 533 * aligned with the satellite, user can send a message and also receive a reply in demo mode. 534 * If enableSatellite is {@code false}, enableDemoMode has no impact on the behavior. 535 * 536 * @param attributes The attributes of the enable request. 537 * @param executor The executor on which the error code listener will be called. 538 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 539 * 540 * @throws SecurityException if the caller doesn't have required permission. 541 */ 542 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 543 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) requestEnabled(@onNull EnableRequestAttributes attributes, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)544 public void requestEnabled(@NonNull EnableRequestAttributes attributes, 545 @NonNull @CallbackExecutor Executor executor, 546 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 547 Objects.requireNonNull(attributes); 548 Objects.requireNonNull(executor); 549 Objects.requireNonNull(resultListener); 550 551 try { 552 ITelephony telephony = getITelephony(); 553 if (telephony != null) { 554 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 555 @Override 556 public void accept(int result) { 557 executor.execute(() -> Binder.withCleanCallingIdentity( 558 () -> resultListener.accept(result))); 559 } 560 }; 561 telephony.requestSatelliteEnabled(mSubId, attributes.isEnabled(), 562 attributes.isDemoMode(), attributes.isEmergencyMode(), errorCallback); 563 } else { 564 Rlog.e(TAG, "requestEnabled() invalid telephony"); 565 executor.execute(() -> Binder.withCleanCallingIdentity( 566 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 567 } 568 } catch (RemoteException ex) { 569 Rlog.e(TAG, "requestEnabled() exception: ", ex); 570 executor.execute(() -> Binder.withCleanCallingIdentity( 571 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 572 } 573 } 574 575 /** 576 * Request to get whether the satellite modem is enabled. 577 * 578 * @param executor The executor on which the callback will be called. 579 * @param callback The callback object to which the result will be delivered. 580 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 581 * will return a {@code boolean} with value {@code true} if the satellite modem 582 * is enabled and {@code false} otherwise. 583 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 584 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 585 * 586 * @throws SecurityException if the caller doesn't have required permission. 587 */ 588 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 589 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) requestIsEnabled(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteException> callback)590 public void requestIsEnabled(@NonNull @CallbackExecutor Executor executor, 591 @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { 592 Objects.requireNonNull(executor); 593 Objects.requireNonNull(callback); 594 595 try { 596 ITelephony telephony = getITelephony(); 597 if (telephony != null) { 598 ResultReceiver receiver = new ResultReceiver(null) { 599 @Override 600 protected void onReceiveResult(int resultCode, Bundle resultData) { 601 if (resultCode == SATELLITE_RESULT_SUCCESS) { 602 if (resultData.containsKey(KEY_SATELLITE_ENABLED)) { 603 boolean isSatelliteEnabled = 604 resultData.getBoolean(KEY_SATELLITE_ENABLED); 605 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 606 callback.onResult(isSatelliteEnabled))); 607 } else { 608 loge("KEY_SATELLITE_ENABLED does not exist."); 609 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 610 callback.onError(new SatelliteException( 611 SATELLITE_RESULT_REQUEST_FAILED)))); 612 } 613 } else { 614 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 615 callback.onError(new SatelliteException(resultCode)))); 616 } 617 } 618 }; 619 telephony.requestIsSatelliteEnabled(mSubId, receiver); 620 } else { 621 loge("requestIsEnabled() invalid telephony"); 622 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 623 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 624 } 625 } catch (RemoteException ex) { 626 loge("requestIsEnabled() RemoteException: " + ex); 627 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 628 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 629 } 630 } 631 632 /** 633 * Request to get whether the satellite service demo mode is enabled. 634 * 635 * @param executor The executor on which the callback will be called. 636 * @param callback The callback object to which the result will be delivered. 637 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 638 * will return a {@code boolean} with value {@code true} if demo mode is enabled 639 * and {@code false} otherwise. 640 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 641 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 642 * 643 * @throws SecurityException if the caller doesn't have required permission. 644 */ 645 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 646 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) requestIsDemoModeEnabled(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteException> callback)647 public void requestIsDemoModeEnabled(@NonNull @CallbackExecutor Executor executor, 648 @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { 649 Objects.requireNonNull(executor); 650 Objects.requireNonNull(callback); 651 652 try { 653 ITelephony telephony = getITelephony(); 654 if (telephony != null) { 655 ResultReceiver receiver = new ResultReceiver(null) { 656 @Override 657 protected void onReceiveResult(int resultCode, Bundle resultData) { 658 if (resultCode == SATELLITE_RESULT_SUCCESS) { 659 if (resultData.containsKey(KEY_DEMO_MODE_ENABLED)) { 660 boolean isDemoModeEnabled = 661 resultData.getBoolean(KEY_DEMO_MODE_ENABLED); 662 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 663 callback.onResult(isDemoModeEnabled))); 664 } else { 665 loge("KEY_DEMO_MODE_ENABLED does not exist."); 666 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 667 callback.onError(new SatelliteException( 668 SATELLITE_RESULT_REQUEST_FAILED)))); 669 } 670 } else { 671 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 672 callback.onError(new SatelliteException(resultCode)))); 673 } 674 } 675 }; 676 telephony.requestIsDemoModeEnabled(mSubId, receiver); 677 } else { 678 loge("requestIsDemoModeEnabled() invalid telephony"); 679 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 680 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 681 } 682 } catch (RemoteException ex) { 683 loge("requestIsDemoModeEnabled() RemoteException: " + ex); 684 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 685 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 686 } 687 } 688 689 /** 690 * Request to get whether the satellite service is enabled for emergency mode. 691 * 692 * @param executor The executor on which the callback will be called. 693 * @param callback The callback object to which the result will be delivered. 694 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 695 * will return a {@code boolean} with value {@code true} if satellite is enabled 696 * for emergency mode and {@code false} otherwise. 697 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 698 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 699 * 700 * @throws SecurityException if the caller doesn't have required permission. 701 */ 702 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 703 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) requestIsEmergencyModeEnabled(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteException> callback)704 public void requestIsEmergencyModeEnabled(@NonNull @CallbackExecutor Executor executor, 705 @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { 706 Objects.requireNonNull(executor); 707 Objects.requireNonNull(callback); 708 709 try { 710 ITelephony telephony = getITelephony(); 711 if (telephony != null) { 712 ResultReceiver receiver = new ResultReceiver(null) { 713 @Override 714 protected void onReceiveResult(int resultCode, Bundle resultData) { 715 if (resultCode == SATELLITE_RESULT_SUCCESS) { 716 if (resultData.containsKey(KEY_EMERGENCY_MODE_ENABLED)) { 717 boolean isEmergencyModeEnabled = 718 resultData.getBoolean(KEY_EMERGENCY_MODE_ENABLED); 719 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 720 callback.onResult(isEmergencyModeEnabled))); 721 } else { 722 loge("KEY_EMERGENCY_MODE_ENABLED does not exist."); 723 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 724 callback.onError(new SatelliteException( 725 SATELLITE_RESULT_REQUEST_FAILED)))); 726 } 727 } else { 728 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 729 callback.onError(new SatelliteException(resultCode)))); 730 } 731 } 732 }; 733 telephony.requestIsEmergencyModeEnabled(mSubId, receiver); 734 } else { 735 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 736 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 737 } 738 } catch (RemoteException ex) { 739 loge("requestIsEmergencyModeEnabled() RemoteException: " + ex); 740 ex.rethrowAsRuntimeException(); 741 } 742 } 743 744 /** 745 * Request to get whether the satellite service is supported on the device. 746 * 747 * <p> 748 * Note: This API only checks whether the device supports the satellite feature. The result will 749 * not be affected by whether the device is provisioned. 750 * </p> 751 * 752 * @param executor The executor on which the callback will be called. 753 * @param callback The callback object to which the result will be delivered. 754 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 755 * will return a {@code boolean} with value {@code true} if the satellite 756 * service is supported on the device and {@code false} otherwise. 757 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 758 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 759 */ 760 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) requestIsSupported(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteException> callback)761 public void requestIsSupported(@NonNull @CallbackExecutor Executor executor, 762 @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { 763 Objects.requireNonNull(executor); 764 Objects.requireNonNull(callback); 765 766 try { 767 ITelephony telephony = getITelephony(); 768 if (telephony != null) { 769 ResultReceiver receiver = new ResultReceiver(null) { 770 @Override 771 protected void onReceiveResult(int resultCode, Bundle resultData) { 772 if (resultCode == SATELLITE_RESULT_SUCCESS) { 773 if (resultData.containsKey(KEY_SATELLITE_SUPPORTED)) { 774 boolean isSatelliteSupported = 775 resultData.getBoolean(KEY_SATELLITE_SUPPORTED); 776 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 777 callback.onResult(isSatelliteSupported))); 778 } else { 779 loge("KEY_SATELLITE_SUPPORTED does not exist."); 780 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 781 callback.onError(new SatelliteException( 782 SATELLITE_RESULT_REQUEST_FAILED)))); 783 } 784 } else { 785 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 786 callback.onError(new SatelliteException(resultCode)))); 787 } 788 } 789 }; 790 telephony.requestIsSatelliteSupported(mSubId, receiver); 791 } else { 792 loge("requestIsSupported() invalid telephony"); 793 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 794 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 795 } 796 } catch (RemoteException ex) { 797 loge("requestIsSupported() RemoteException: " + ex); 798 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 799 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 800 } 801 } 802 803 /** 804 * Request to get the {@link SatelliteCapabilities} of the satellite service. 805 * 806 * @param executor The executor on which the callback will be called. 807 * @param callback The callback object to which the result will be delivered. 808 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 809 * will return the {@link SatelliteCapabilities} of the satellite service. 810 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 811 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 812 * 813 * @throws SecurityException if the caller doesn't have required permission. 814 */ 815 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 816 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) requestCapabilities(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<SatelliteCapabilities, SatelliteException> callback)817 public void requestCapabilities(@NonNull @CallbackExecutor Executor executor, 818 @NonNull OutcomeReceiver<SatelliteCapabilities, SatelliteException> callback) { 819 Objects.requireNonNull(executor); 820 Objects.requireNonNull(callback); 821 822 try { 823 ITelephony telephony = getITelephony(); 824 if (telephony != null) { 825 ResultReceiver receiver = new ResultReceiver(null) { 826 @Override 827 protected void onReceiveResult(int resultCode, Bundle resultData) { 828 if (resultCode == SATELLITE_RESULT_SUCCESS) { 829 if (resultData.containsKey(KEY_SATELLITE_CAPABILITIES)) { 830 SatelliteCapabilities capabilities = 831 resultData.getParcelable(KEY_SATELLITE_CAPABILITIES, 832 SatelliteCapabilities.class); 833 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 834 callback.onResult(capabilities))); 835 } else { 836 loge("KEY_SATELLITE_CAPABILITIES does not exist."); 837 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 838 callback.onError(new SatelliteException( 839 SATELLITE_RESULT_REQUEST_FAILED)))); 840 } 841 } else { 842 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 843 callback.onError(new SatelliteException(resultCode)))); 844 } 845 } 846 }; 847 telephony.requestSatelliteCapabilities(mSubId, receiver); 848 } else { 849 loge("requestCapabilities() invalid telephony"); 850 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 851 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 852 } 853 } catch (RemoteException ex) { 854 loge("requestCapabilities() RemoteException: " + ex); 855 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 856 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 857 } 858 } 859 860 /** 861 * The default state indicating that datagram transfer is idle. 862 * This should be sent if there are no message transfer activity happening. 863 */ 864 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 865 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE = 0; 866 /** 867 * A transition state indicating that a datagram is being sent. 868 */ 869 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 870 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING = 1; 871 /** 872 * An end state indicating that datagram sending completed successfully. 873 * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE} 874 * will be sent if no more messages are pending. 875 */ 876 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 877 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS = 2; 878 /** 879 * An end state indicating that datagram sending completed with a failure. 880 * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE} 881 * must be sent before reporting any additional datagram transfer state changes. All pending 882 * messages will be reported as failed, to the corresponding applications. 883 */ 884 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 885 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED = 3; 886 /** 887 * A transition state indicating that a datagram is being received. 888 */ 889 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 890 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING = 4; 891 /** 892 * An end state indicating that datagram receiving completed successfully. 893 * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE} 894 * will be sent if no more messages are pending. 895 */ 896 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 897 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS = 5; 898 /** 899 * An end state indicating that datagram receive operation found that there are no 900 * messages to be retrieved from the satellite. 901 * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE} 902 * will be sent if no more messages are pending. 903 */ 904 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 905 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE = 6; 906 /** 907 * An end state indicating that datagram receive completed with a failure. 908 * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE} 909 * will be sent if no more messages are pending. 910 */ 911 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 912 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED = 7; 913 /** 914 * A transition state indicating that Telephony is waiting for satellite modem to connect to a 915 * satellite network before sending a datagram or polling for datagrams. If the satellite modem 916 * successfully connects to a satellite network, either 917 * {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING} or 918 * {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING} will be sent. Otherwise, 919 * either {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED} or 920 * {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED} will be sent. 921 */ 922 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 923 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT = 8; 924 /** 925 * The datagram transfer state is unknown. This generic datagram transfer state should be used 926 * only when the datagram transfer state cannot be mapped to other specific datagram transfer 927 * states. 928 */ 929 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 930 public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN = -1; 931 932 /** @hide */ 933 @IntDef(prefix = {"SATELLITE_DATAGRAM_TRANSFER_STATE_"}, value = { 934 SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 935 SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, 936 SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS, 937 SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED, 938 SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING, 939 SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS, 940 SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE, 941 SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED, 942 SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT, 943 SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN 944 }) 945 @Retention(RetentionPolicy.SOURCE) 946 public @interface SatelliteDatagramTransferState {} 947 // TODO: Split into two enums for sending and receiving states 948 949 /** 950 * Satellite modem is in idle state. 951 */ 952 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 953 public static final int SATELLITE_MODEM_STATE_IDLE = 0; 954 /** 955 * Satellite modem is listening for incoming datagrams. 956 */ 957 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 958 public static final int SATELLITE_MODEM_STATE_LISTENING = 1; 959 /** 960 * Satellite modem is sending and/or receiving datagrams. 961 */ 962 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 963 public static final int SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING = 2; 964 /** 965 * Satellite modem is retrying to send and/or receive datagrams. 966 */ 967 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 968 public static final int SATELLITE_MODEM_STATE_DATAGRAM_RETRYING = 3; 969 /** 970 * Satellite modem is powered off. 971 */ 972 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 973 public static final int SATELLITE_MODEM_STATE_OFF = 4; 974 /** 975 * Satellite modem is unavailable. 976 */ 977 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 978 public static final int SATELLITE_MODEM_STATE_UNAVAILABLE = 5; 979 /** 980 * The satellite modem is powered on but the device is not registered to a satellite cell. 981 */ 982 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 983 public static final int SATELLITE_MODEM_STATE_NOT_CONNECTED = 6; 984 /** 985 * The satellite modem is powered on and the device is registered to a satellite cell. 986 */ 987 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 988 public static final int SATELLITE_MODEM_STATE_CONNECTED = 7; 989 /** 990 * The satellite modem is being powered on. 991 * @hide 992 */ 993 public static final int SATELLITE_MODEM_STATE_ENABLING_SATELLITE = 8; 994 /** 995 * The satellite modem is being powered off. 996 * @hide 997 */ 998 public static final int SATELLITE_MODEM_STATE_DISABLING_SATELLITE = 9; 999 /** 1000 * Satellite modem state is unknown. This generic modem state should be used only when the 1001 * modem state cannot be mapped to other specific modem states. 1002 */ 1003 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 1004 public static final int SATELLITE_MODEM_STATE_UNKNOWN = -1; 1005 1006 /** @hide */ 1007 @IntDef(prefix = {"SATELLITE_MODEM_STATE_"}, value = { 1008 SATELLITE_MODEM_STATE_IDLE, 1009 SATELLITE_MODEM_STATE_LISTENING, 1010 SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING, 1011 SATELLITE_MODEM_STATE_DATAGRAM_RETRYING, 1012 SATELLITE_MODEM_STATE_OFF, 1013 SATELLITE_MODEM_STATE_UNAVAILABLE, 1014 SATELLITE_MODEM_STATE_NOT_CONNECTED, 1015 SATELLITE_MODEM_STATE_CONNECTED, 1016 SATELLITE_MODEM_STATE_ENABLING_SATELLITE, 1017 SATELLITE_MODEM_STATE_DISABLING_SATELLITE, 1018 SATELLITE_MODEM_STATE_UNKNOWN 1019 }) 1020 @Retention(RetentionPolicy.SOURCE) 1021 public @interface SatelliteModemState {} 1022 1023 /** 1024 * Datagram type is unknown. This generic datagram type should be used only when the 1025 * datagram type cannot be mapped to other specific datagram types. 1026 */ 1027 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 1028 public static final int DATAGRAM_TYPE_UNKNOWN = 0; 1029 /** 1030 * Datagram type indicating that the datagram to be sent or received is of type SOS message. 1031 */ 1032 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 1033 public static final int DATAGRAM_TYPE_SOS_MESSAGE = 1; 1034 /** 1035 * Datagram type indicating that the datagram to be sent or received is of type 1036 * location sharing. 1037 */ 1038 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 1039 public static final int DATAGRAM_TYPE_LOCATION_SHARING = 2; 1040 /** 1041 * This type of datagram is used to keep the device in satellite connected state or check if 1042 * there is any incoming message. 1043 * @hide 1044 */ 1045 public static final int DATAGRAM_TYPE_KEEP_ALIVE = 3; 1046 /** 1047 * Datagram type indicating that the datagram to be sent or received is of type SOS message and 1048 * is the last message to emergency service provider indicating still needs help. 1049 * @hide 1050 */ 1051 public static final int DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP = 4; 1052 /** 1053 * Datagram type indicating that the datagram to be sent or received is of type SOS message and 1054 * is the last message to emergency service provider indicating no more help is needed. 1055 * @hide 1056 */ 1057 public static final int DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED = 5; 1058 1059 /** @hide */ 1060 @IntDef(prefix = "DATAGRAM_TYPE_", value = { 1061 DATAGRAM_TYPE_UNKNOWN, 1062 DATAGRAM_TYPE_SOS_MESSAGE, 1063 DATAGRAM_TYPE_LOCATION_SHARING, 1064 DATAGRAM_TYPE_KEEP_ALIVE, 1065 DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP, 1066 DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED 1067 }) 1068 @Retention(RetentionPolicy.SOURCE) 1069 public @interface DatagramType {} 1070 1071 /** 1072 * Satellite communication restricted by user. 1073 * @hide 1074 */ 1075 public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER = 0; 1076 1077 /** 1078 * Satellite communication restricted by geolocation. This can be 1079 * triggered based upon geofence input provided by carrier to enable or disable satellite. 1080 */ 1081 @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) 1082 public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION = 1; 1083 1084 /** 1085 * Satellite communication restricted by entitlement server. This can be triggered based on 1086 * the EntitlementStatus value received from the entitlement server to enable or disable 1087 * satellite. 1088 */ 1089 @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) 1090 public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT = 2; 1091 1092 /** @hide */ 1093 @IntDef(prefix = "SATELLITE_COMMUNICATION_RESTRICTION_REASON_", value = { 1094 SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, 1095 SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION, 1096 SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT 1097 }) 1098 @Retention(RetentionPolicy.SOURCE) 1099 public @interface SatelliteCommunicationRestrictionReason {} 1100 1101 /** 1102 * Start receiving satellite transmission updates. 1103 * This can be called by the pointing UI when the user starts pointing to the satellite. 1104 * Modem should continue to report the pointing input as the device or satellite moves. 1105 * Satellite transmission updates are started only on {@link #SATELLITE_RESULT_SUCCESS}. 1106 * All other results indicate that this operation failed. 1107 * Once satellite transmission updates begin, position and datagram transfer state updates 1108 * will be sent through {@link SatelliteTransmissionUpdateCallback}. 1109 * 1110 * @param executor The executor on which the callback and error code listener will be called. 1111 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 1112 * @param callback The callback to notify of satellite transmission updates. 1113 * 1114 * @throws SecurityException if the caller doesn't have required permission. 1115 */ 1116 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1117 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) 1118 @SuppressWarnings("SamShouldBeLast") startTransmissionUpdates(@onNull @allbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener, @NonNull SatelliteTransmissionUpdateCallback callback)1119 public void startTransmissionUpdates(@NonNull @CallbackExecutor Executor executor, 1120 @SatelliteResult @NonNull Consumer<Integer> resultListener, 1121 @NonNull SatelliteTransmissionUpdateCallback callback) { 1122 Objects.requireNonNull(executor); 1123 Objects.requireNonNull(resultListener); 1124 Objects.requireNonNull(callback); 1125 1126 try { 1127 ITelephony telephony = getITelephony(); 1128 if (telephony != null) { 1129 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 1130 @Override 1131 public void accept(int result) { 1132 executor.execute(() -> Binder.withCleanCallingIdentity( 1133 () -> resultListener.accept(result))); 1134 } 1135 }; 1136 ISatelliteTransmissionUpdateCallback internalCallback = 1137 new ISatelliteTransmissionUpdateCallback.Stub() { 1138 1139 @Override 1140 public void onSatellitePositionChanged(PointingInfo pointingInfo) { 1141 executor.execute(() -> Binder.withCleanCallingIdentity( 1142 () -> callback.onSatellitePositionChanged(pointingInfo))); 1143 } 1144 1145 @Override 1146 public void onSendDatagramStateChanged(int datagramType, int state, 1147 int sendPendingCount, int errorCode) { 1148 executor.execute(() -> Binder.withCleanCallingIdentity( 1149 () -> callback.onSendDatagramStateChanged(datagramType, 1150 state, sendPendingCount, errorCode))); 1151 1152 // For backward compatibility 1153 executor.execute(() -> Binder.withCleanCallingIdentity( 1154 () -> callback.onSendDatagramStateChanged( 1155 state, sendPendingCount, errorCode))); 1156 } 1157 1158 @Override 1159 public void onReceiveDatagramStateChanged(int state, 1160 int receivePendingCount, int errorCode) { 1161 executor.execute(() -> Binder.withCleanCallingIdentity( 1162 () -> callback.onReceiveDatagramStateChanged( 1163 state, receivePendingCount, errorCode))); 1164 } 1165 }; 1166 sSatelliteTransmissionUpdateCallbackMap.put(callback, internalCallback); 1167 telephony.startSatelliteTransmissionUpdates(mSubId, errorCallback, 1168 internalCallback); 1169 } else { 1170 loge("startTransmissionUpdates() invalid telephony"); 1171 executor.execute(() -> Binder.withCleanCallingIdentity( 1172 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1173 } 1174 } catch (RemoteException ex) { 1175 loge("startTransmissionUpdates() RemoteException: " + ex); 1176 executor.execute(() -> Binder.withCleanCallingIdentity( 1177 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1178 } 1179 } 1180 1181 /** 1182 * Stop receiving satellite transmission updates. 1183 * This can be called by the pointing UI when the user stops pointing to the satellite. 1184 * Satellite transmission updates are stopped and the callback is unregistered only on 1185 * {@link #SATELLITE_RESULT_SUCCESS}. All other results that this operation failed. 1186 * 1187 * @param callback The callback that was passed to {@link 1188 * #startTransmissionUpdates(Executor, Consumer, SatelliteTransmissionUpdateCallback)}. 1189 * @param executor The executor on which the error code listener will be called. 1190 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 1191 * 1192 * @throws SecurityException if the caller doesn't have required permission. 1193 */ 1194 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1195 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) stopTransmissionUpdates(@onNull SatelliteTransmissionUpdateCallback callback, @SuppressWarnings("ListenerLast") @NonNull @CallbackExecutor Executor executor, @SuppressWarnings("ListenerLast") @SatelliteResult @NonNull Consumer<Integer> resultListener)1196 public void stopTransmissionUpdates(@NonNull SatelliteTransmissionUpdateCallback callback, 1197 @SuppressWarnings("ListenerLast") @NonNull @CallbackExecutor Executor executor, 1198 @SuppressWarnings("ListenerLast") @SatelliteResult @NonNull 1199 Consumer<Integer> resultListener) { 1200 Objects.requireNonNull(callback); 1201 Objects.requireNonNull(executor); 1202 Objects.requireNonNull(resultListener); 1203 1204 ISatelliteTransmissionUpdateCallback internalCallback = 1205 sSatelliteTransmissionUpdateCallbackMap.remove(callback); 1206 1207 try { 1208 ITelephony telephony = getITelephony(); 1209 if (telephony != null) { 1210 if (internalCallback != null) { 1211 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 1212 @Override 1213 public void accept(int result) { 1214 executor.execute(() -> Binder.withCleanCallingIdentity( 1215 () -> resultListener.accept(result))); 1216 } 1217 }; 1218 telephony.stopSatelliteTransmissionUpdates(mSubId, errorCallback, 1219 internalCallback); 1220 // TODO: Notify SmsHandler that pointing UI stopped 1221 } else { 1222 loge("stopSatelliteTransmissionUpdates: No internal callback."); 1223 executor.execute(() -> Binder.withCleanCallingIdentity( 1224 () -> resultListener.accept(SATELLITE_RESULT_INVALID_ARGUMENTS))); 1225 } 1226 } else { 1227 loge("stopTransmissionUpdates() invalid telephony"); 1228 executor.execute(() -> Binder.withCleanCallingIdentity( 1229 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1230 } 1231 } catch (RemoteException ex) { 1232 loge("stopTransmissionUpdates() RemoteException: " + ex); 1233 executor.execute(() -> Binder.withCleanCallingIdentity( 1234 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1235 } 1236 } 1237 1238 /** 1239 * Provision the device with a satellite provider. 1240 * This is needed if the provider allows dynamic registration. 1241 * 1242 * @param token The token is generated by the user which is used as a unique identifier for 1243 * provisioning with satellite gateway. 1244 * @param provisionData Data from the provisioning app that can be used by provisioning server 1245 * @param cancellationSignal The optional signal used by the caller to cancel the provision 1246 * request. Even when the cancellation is signaled, Telephony will 1247 * still trigger the callback to return the result of this request. 1248 * @param executor The executor on which the error code listener will be called. 1249 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 1250 * 1251 * @throws SecurityException if the caller doesn't have required permission. 1252 */ 1253 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1254 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) provisionService(@onNull String token, @NonNull byte[] provisionData, @Nullable CancellationSignal cancellationSignal, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)1255 public void provisionService(@NonNull String token, @NonNull byte[] provisionData, 1256 @Nullable CancellationSignal cancellationSignal, 1257 @NonNull @CallbackExecutor Executor executor, 1258 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 1259 Objects.requireNonNull(token); 1260 Objects.requireNonNull(executor); 1261 Objects.requireNonNull(resultListener); 1262 Objects.requireNonNull(provisionData); 1263 1264 ICancellationSignal cancelRemote = null; 1265 try { 1266 ITelephony telephony = getITelephony(); 1267 if (telephony != null) { 1268 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 1269 @Override 1270 public void accept(int result) { 1271 executor.execute(() -> Binder.withCleanCallingIdentity( 1272 () -> resultListener.accept(result))); 1273 } 1274 }; 1275 cancelRemote = telephony.provisionSatelliteService(mSubId, token, provisionData, 1276 errorCallback); 1277 } else { 1278 loge("provisionService() invalid telephony"); 1279 executor.execute(() -> Binder.withCleanCallingIdentity( 1280 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1281 } 1282 } catch (RemoteException ex) { 1283 loge("provisionService() RemoteException=" + ex); 1284 executor.execute(() -> Binder.withCleanCallingIdentity( 1285 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1286 } 1287 if (cancellationSignal != null) { 1288 cancellationSignal.setRemote(cancelRemote); 1289 } 1290 } 1291 1292 /** 1293 * Deprovision the device with the satellite provider. 1294 * This is needed if the provider allows dynamic registration. Once deprovisioned, 1295 * {@link SatelliteProvisionStateCallback#onSatelliteProvisionStateChanged(boolean)} 1296 * should report as deprovisioned. 1297 * For provisioning satellite service, refer to 1298 * {@link #provisionService(String, byte[], CancellationSignal, Executor, Consumer)} 1299 * 1300 * @param token The token of the device/subscription to be deprovisioned. 1301 * This should match with the token passed as input in 1302 * {@link #provisionService(String, byte[], CancellationSignal, Executor, 1303 * Consumer)} 1304 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 1305 * 1306 * @throws SecurityException if the caller doesn't have required permission. 1307 */ 1308 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1309 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) deprovisionService(@onNull String token, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)1310 public void deprovisionService(@NonNull String token, 1311 @NonNull @CallbackExecutor Executor executor, 1312 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 1313 Objects.requireNonNull(token); 1314 Objects.requireNonNull(executor); 1315 Objects.requireNonNull(resultListener); 1316 1317 try { 1318 ITelephony telephony = getITelephony(); 1319 if (telephony != null) { 1320 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 1321 @Override 1322 public void accept(int result) { 1323 executor.execute(() -> Binder.withCleanCallingIdentity( 1324 () -> resultListener.accept(result))); 1325 } 1326 }; 1327 telephony.deprovisionSatelliteService(mSubId, token, errorCallback); 1328 } else { 1329 loge("deprovisionService() invalid telephony"); 1330 executor.execute(() -> Binder.withCleanCallingIdentity( 1331 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1332 } 1333 } catch (RemoteException ex) { 1334 loge("deprovisionService() RemoteException ex=" + ex); 1335 executor.execute(() -> Binder.withCleanCallingIdentity( 1336 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1337 } 1338 } 1339 1340 /** 1341 * Registers for the satellite provision state changed. 1342 * 1343 * @param executor The executor on which the callback will be called. 1344 * @param callback The callback to handle the satellite provision state changed event. 1345 * 1346 * @return The {@link SatelliteResult} result of the operation. 1347 * 1348 * @throws SecurityException if the caller doesn't have required permission. 1349 * @throws IllegalStateException if the Telephony process is not currently available. 1350 */ 1351 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1352 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) registerForProvisionStateChanged( @onNull @allbackExecutor Executor executor, @NonNull SatelliteProvisionStateCallback callback)1353 @SatelliteResult public int registerForProvisionStateChanged( 1354 @NonNull @CallbackExecutor Executor executor, 1355 @NonNull SatelliteProvisionStateCallback callback) { 1356 Objects.requireNonNull(executor); 1357 Objects.requireNonNull(callback); 1358 1359 try { 1360 ITelephony telephony = getITelephony(); 1361 if (telephony != null) { 1362 ISatelliteProvisionStateCallback internalCallback = 1363 new ISatelliteProvisionStateCallback.Stub() { 1364 @Override 1365 public void onSatelliteProvisionStateChanged(boolean provisioned) { 1366 executor.execute(() -> Binder.withCleanCallingIdentity( 1367 () -> callback.onSatelliteProvisionStateChanged( 1368 provisioned))); 1369 } 1370 }; 1371 sSatelliteProvisionStateCallbackMap.put(callback, internalCallback); 1372 return telephony.registerForSatelliteProvisionStateChanged( 1373 mSubId, internalCallback); 1374 } else { 1375 throw new IllegalStateException("telephony service is null."); 1376 } 1377 } catch (RemoteException ex) { 1378 loge("registerForProvisionStateChanged() RemoteException: " + ex); 1379 ex.rethrowAsRuntimeException(); 1380 } 1381 return SATELLITE_RESULT_REQUEST_FAILED; 1382 } 1383 1384 /** 1385 * Unregisters for the satellite provision state changed. 1386 * If callback was not registered before, the request will be ignored. 1387 * 1388 * @param callback The callback that was passed to 1389 * {@link #registerForProvisionStateChanged(Executor, SatelliteProvisionStateCallback)} 1390 * 1391 * @throws SecurityException if the caller doesn't have required permission. 1392 * @throws IllegalStateException if the Telephony process is not currently available. 1393 */ 1394 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1395 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) unregisterForProvisionStateChanged( @onNull SatelliteProvisionStateCallback callback)1396 public void unregisterForProvisionStateChanged( 1397 @NonNull SatelliteProvisionStateCallback callback) { 1398 Objects.requireNonNull(callback); 1399 ISatelliteProvisionStateCallback internalCallback = 1400 sSatelliteProvisionStateCallbackMap.remove(callback); 1401 1402 try { 1403 ITelephony telephony = getITelephony(); 1404 if (telephony != null) { 1405 if (internalCallback != null) { 1406 telephony.unregisterForSatelliteProvisionStateChanged(mSubId, internalCallback); 1407 } else { 1408 loge("unregisterForProvisionStateChanged: No internal callback."); 1409 } 1410 } else { 1411 throw new IllegalStateException("telephony service is null."); 1412 } 1413 } catch (RemoteException ex) { 1414 loge("unregisterForProvisionStateChanged() RemoteException: " + ex); 1415 ex.rethrowAsRuntimeException(); 1416 } 1417 } 1418 1419 /** 1420 * Request to get whether this device is provisioned with a satellite provider. 1421 * 1422 * @param executor The executor on which the callback will be called. 1423 * @param callback The callback object to which the result will be delivered. 1424 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 1425 * will return a {@code boolean} with value {@code true} if the device is 1426 * provisioned with a satellite provider and {@code false} otherwise. 1427 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 1428 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 1429 * 1430 * @throws SecurityException if the caller doesn't have required permission. 1431 */ 1432 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1433 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) requestIsProvisioned(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteException> callback)1434 public void requestIsProvisioned(@NonNull @CallbackExecutor Executor executor, 1435 @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { 1436 Objects.requireNonNull(executor); 1437 Objects.requireNonNull(callback); 1438 1439 try { 1440 ITelephony telephony = getITelephony(); 1441 if (telephony != null) { 1442 ResultReceiver receiver = new ResultReceiver(null) { 1443 @Override 1444 protected void onReceiveResult(int resultCode, Bundle resultData) { 1445 if (resultCode == SATELLITE_RESULT_SUCCESS) { 1446 if (resultData.containsKey(KEY_SATELLITE_PROVISIONED)) { 1447 boolean isSatelliteProvisioned = 1448 resultData.getBoolean(KEY_SATELLITE_PROVISIONED); 1449 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1450 callback.onResult(isSatelliteProvisioned))); 1451 } else { 1452 loge("KEY_SATELLITE_PROVISIONED does not exist."); 1453 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1454 callback.onError(new SatelliteException( 1455 SATELLITE_RESULT_REQUEST_FAILED)))); 1456 } 1457 } else { 1458 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1459 callback.onError(new SatelliteException(resultCode)))); 1460 } 1461 } 1462 }; 1463 telephony.requestIsSatelliteProvisioned(mSubId, receiver); 1464 } else { 1465 loge("requestIsProvisioned() invalid telephony"); 1466 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 1467 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 1468 } 1469 } catch (RemoteException ex) { 1470 loge("requestIsProvisioned() RemoteException: " + ex); 1471 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 1472 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 1473 } 1474 } 1475 1476 /** 1477 * Registers for modem state changed from satellite modem. 1478 * 1479 * @param executor The executor on which the callback will be called. 1480 * @param callback The callback to handle the satellite modem state changed event. 1481 * 1482 * @return The {@link SatelliteResult} result of the operation. 1483 * 1484 * @throws SecurityException if the caller doesn't have required permission. 1485 * @throws IllegalStateException if the Telephony process is not currently available. 1486 */ 1487 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1488 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) registerForModemStateChanged( @onNull @allbackExecutor Executor executor, @NonNull SatelliteModemStateCallback callback)1489 @SatelliteResult public int registerForModemStateChanged( 1490 @NonNull @CallbackExecutor Executor executor, 1491 @NonNull SatelliteModemStateCallback callback) { 1492 Objects.requireNonNull(executor); 1493 Objects.requireNonNull(callback); 1494 1495 try { 1496 ITelephony telephony = getITelephony(); 1497 if (telephony != null) { 1498 ISatelliteModemStateCallback internalCallback = 1499 new ISatelliteModemStateCallback.Stub() { 1500 @Override 1501 public void onSatelliteModemStateChanged(int state) { 1502 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1503 callback.onSatelliteModemStateChanged(state))); 1504 } 1505 }; 1506 sSatelliteModemStateCallbackMap.put(callback, internalCallback); 1507 return telephony.registerForSatelliteModemStateChanged(mSubId, internalCallback); 1508 } else { 1509 throw new IllegalStateException("telephony service is null."); 1510 } 1511 } catch (RemoteException ex) { 1512 loge("registerForModemStateChanged() RemoteException:" + ex); 1513 ex.rethrowAsRuntimeException(); 1514 } 1515 return SATELLITE_RESULT_REQUEST_FAILED; 1516 } 1517 1518 /** 1519 * Unregisters for modem state changed from satellite modem. 1520 * If callback was not registered before, the request will be ignored. 1521 * 1522 * @param callback The callback that was passed to 1523 * {@link #registerForModemStateChanged(Executor, SatelliteModemStateCallback)}. 1524 * 1525 * @throws SecurityException if the caller doesn't have required permission. 1526 * @throws IllegalStateException if the Telephony process is not currently available. 1527 */ 1528 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1529 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) unregisterForModemStateChanged( @onNull SatelliteModemStateCallback callback)1530 public void unregisterForModemStateChanged( 1531 @NonNull SatelliteModemStateCallback callback) { 1532 Objects.requireNonNull(callback); 1533 ISatelliteModemStateCallback internalCallback = sSatelliteModemStateCallbackMap.remove( 1534 callback); 1535 1536 try { 1537 ITelephony telephony = getITelephony(); 1538 if (telephony != null) { 1539 if (internalCallback != null) { 1540 telephony.unregisterForModemStateChanged(mSubId, internalCallback); 1541 } else { 1542 loge("unregisterForModemStateChanged: No internal callback."); 1543 } 1544 } else { 1545 throw new IllegalStateException("telephony service is null."); 1546 } 1547 } catch (RemoteException ex) { 1548 loge("unregisterForModemStateChanged() RemoteException:" + ex); 1549 ex.rethrowAsRuntimeException(); 1550 } 1551 } 1552 1553 /** 1554 * Register to receive incoming datagrams over satellite. 1555 * 1556 * To poll for pending satellite datagrams, refer to 1557 * {@link #pollPendingDatagrams(Executor, Consumer)} 1558 * 1559 * @param executor The executor on which the callback will be called. 1560 * @param callback The callback to handle incoming datagrams over satellite. 1561 * This callback with be invoked when a new datagram is received from satellite. 1562 * 1563 * @return The {@link SatelliteResult} result of the operation. 1564 * 1565 * @throws SecurityException if the caller doesn't have required permission. 1566 * @throws IllegalStateException if the Telephony process is not currently available. 1567 */ 1568 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1569 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) registerForIncomingDatagram( @onNull @allbackExecutor Executor executor, @NonNull SatelliteDatagramCallback callback)1570 @SatelliteResult public int registerForIncomingDatagram( 1571 @NonNull @CallbackExecutor Executor executor, 1572 @NonNull SatelliteDatagramCallback callback) { 1573 Objects.requireNonNull(executor); 1574 Objects.requireNonNull(callback); 1575 1576 try { 1577 ITelephony telephony = getITelephony(); 1578 if (telephony != null) { 1579 ISatelliteDatagramCallback internalCallback = 1580 new ISatelliteDatagramCallback.Stub() { 1581 @Override 1582 public void onSatelliteDatagramReceived(long datagramId, 1583 @NonNull SatelliteDatagram datagram, int pendingCount, 1584 @NonNull IVoidConsumer internalAck) { 1585 Consumer<Void> externalAck = new Consumer<Void>() { 1586 @Override 1587 public void accept(Void result) { 1588 try { 1589 internalAck.accept(); 1590 } catch (RemoteException e) { 1591 logd("onSatelliteDatagramReceived " 1592 + "RemoteException: " + e); 1593 } 1594 } 1595 }; 1596 1597 executor.execute(() -> Binder.withCleanCallingIdentity( 1598 () -> callback.onSatelliteDatagramReceived( 1599 datagramId, datagram, pendingCount, externalAck))); 1600 } 1601 }; 1602 sSatelliteDatagramCallbackMap.put(callback, internalCallback); 1603 return telephony.registerForIncomingDatagram(mSubId, internalCallback); 1604 } else { 1605 throw new IllegalStateException("telephony service is null."); 1606 } 1607 } catch (RemoteException ex) { 1608 loge("registerForIncomingDatagram() RemoteException:" + ex); 1609 ex.rethrowAsRuntimeException(); 1610 } 1611 return SATELLITE_RESULT_REQUEST_FAILED; 1612 } 1613 1614 /** 1615 * Unregister to stop receiving incoming datagrams over satellite. 1616 * If callback was not registered before, the request will be ignored. 1617 * 1618 * @param callback The callback that was passed to 1619 * {@link #registerForIncomingDatagram(Executor, SatelliteDatagramCallback)}. 1620 * 1621 * @throws SecurityException if the caller doesn't have required permission. 1622 * @throws IllegalStateException if the Telephony process is not currently available. 1623 */ 1624 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1625 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) unregisterForIncomingDatagram(@onNull SatelliteDatagramCallback callback)1626 public void unregisterForIncomingDatagram(@NonNull SatelliteDatagramCallback callback) { 1627 Objects.requireNonNull(callback); 1628 ISatelliteDatagramCallback internalCallback = 1629 sSatelliteDatagramCallbackMap.remove(callback); 1630 1631 try { 1632 ITelephony telephony = getITelephony(); 1633 if (telephony != null) { 1634 if (internalCallback != null) { 1635 telephony.unregisterForIncomingDatagram(mSubId, internalCallback); 1636 } else { 1637 loge("unregisterForIncomingDatagram: No internal callback."); 1638 } 1639 } else { 1640 throw new IllegalStateException("telephony service is null."); 1641 } 1642 } catch (RemoteException ex) { 1643 loge("unregisterForIncomingDatagram() RemoteException:" + ex); 1644 ex.rethrowAsRuntimeException(); 1645 } 1646 } 1647 1648 /** 1649 * Poll pending satellite datagrams over satellite. 1650 * 1651 * This method should be called when user specifies to check incoming messages over satellite. 1652 * This method requests modem to check if there are any pending datagrams to be received over 1653 * satellite. If there are any incoming datagrams, they will be received via 1654 * {@link SatelliteDatagramCallback#onSatelliteDatagramReceived(long, SatelliteDatagram, int, 1655 * Consumer)} )} 1656 * 1657 * @param executor The executor on which the result listener will be called. 1658 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 1659 * 1660 * @throws SecurityException if the caller doesn't have required permission. 1661 */ 1662 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1663 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) pollPendingDatagrams(@onNull @allbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)1664 public void pollPendingDatagrams(@NonNull @CallbackExecutor Executor executor, 1665 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 1666 Objects.requireNonNull(executor); 1667 Objects.requireNonNull(resultListener); 1668 1669 try { 1670 ITelephony telephony = getITelephony(); 1671 if (telephony != null) { 1672 IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() { 1673 @Override 1674 public void accept(int result) { 1675 executor.execute(() -> Binder.withCleanCallingIdentity( 1676 () -> resultListener.accept(result))); 1677 } 1678 }; 1679 telephony.pollPendingDatagrams(mSubId, internalCallback); 1680 } else { 1681 loge("pollPendingDatagrams() invalid telephony"); 1682 executor.execute(() -> Binder.withCleanCallingIdentity( 1683 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1684 } 1685 } catch (RemoteException ex) { 1686 loge("pollPendingDatagrams() RemoteException:" + ex); 1687 executor.execute(() -> Binder.withCleanCallingIdentity( 1688 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1689 } 1690 } 1691 1692 /** 1693 * Send datagram over satellite. 1694 * 1695 * Gateway encodes SOS message or location sharing message into a datagram and passes it as 1696 * input to this method. Datagram received here will be passed down to modem without any 1697 * encoding or encryption. 1698 * 1699 * @param datagramType datagram type indicating whether the datagram is of type 1700 * SOS_SMS or LOCATION_SHARING. 1701 * @param datagram encoded gateway datagram which is encrypted by the caller. 1702 * Datagram will be passed down to modem without any encoding or encryption. 1703 * @param needFullScreenPointingUI If set to true, this indicates pointingUI app to open in full 1704 * screen mode if satellite communication needs pointingUI. 1705 * If this is set to false, pointingUI may be presented to the 1706 * user in collapsed view. Application may decide to mark this 1707 * flag as true when the user is sending data for the first time 1708 * or whenever there is a considerable idle time between 1709 * satellite activity. This decision should be done based upon 1710 * user activity and the application's ability to determine the 1711 * best possible UX experience for the user. 1712 * @param executor The executor on which the result 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 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1718 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) sendDatagram(@atagramType int datagramType, @NonNull SatelliteDatagram datagram, boolean needFullScreenPointingUI, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)1719 public void sendDatagram(@DatagramType int datagramType, 1720 @NonNull SatelliteDatagram datagram, boolean needFullScreenPointingUI, 1721 @NonNull @CallbackExecutor Executor executor, 1722 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 1723 Objects.requireNonNull(datagram); 1724 Objects.requireNonNull(executor); 1725 Objects.requireNonNull(resultListener); 1726 1727 try { 1728 ITelephony telephony = getITelephony(); 1729 if (telephony != null) { 1730 IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() { 1731 @Override 1732 public void accept(int result) { 1733 executor.execute(() -> Binder.withCleanCallingIdentity( 1734 () -> resultListener.accept(result))); 1735 } 1736 }; 1737 telephony.sendDatagram(mSubId, datagramType, datagram, 1738 needFullScreenPointingUI, internalCallback); 1739 } else { 1740 loge("sendDatagram() invalid telephony"); 1741 executor.execute(() -> Binder.withCleanCallingIdentity( 1742 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1743 } 1744 } catch (RemoteException ex) { 1745 loge("sendDatagram() RemoteException:" + ex); 1746 executor.execute(() -> Binder.withCleanCallingIdentity( 1747 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 1748 } 1749 } 1750 1751 /** 1752 * Request to get whether satellite communication is allowed for the current location. 1753 * 1754 * @param executor The executor on which the callback will be called. 1755 * @param callback The callback object to which the result will be delivered. 1756 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 1757 * will return a {@code boolean} with value {@code true} if satellite 1758 * communication is allowed for the current location and 1759 * {@code false} otherwise. 1760 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 1761 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 1762 * 1763 * @throws SecurityException if the caller doesn't have required permission. 1764 */ 1765 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1766 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) requestIsCommunicationAllowedForCurrentLocation( @onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteException> callback)1767 public void requestIsCommunicationAllowedForCurrentLocation( 1768 @NonNull @CallbackExecutor Executor executor, 1769 @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { 1770 Objects.requireNonNull(executor); 1771 Objects.requireNonNull(callback); 1772 1773 try { 1774 ITelephony telephony = getITelephony(); 1775 if (telephony != null) { 1776 ResultReceiver receiver = new ResultReceiver(null) { 1777 @Override 1778 protected void onReceiveResult(int resultCode, Bundle resultData) { 1779 if (resultCode == SATELLITE_RESULT_SUCCESS) { 1780 if (resultData.containsKey(KEY_SATELLITE_COMMUNICATION_ALLOWED)) { 1781 boolean isSatelliteCommunicationAllowed = 1782 resultData.getBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED); 1783 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1784 callback.onResult(isSatelliteCommunicationAllowed))); 1785 } else { 1786 loge("KEY_SATELLITE_COMMUNICATION_ALLOWED does not exist."); 1787 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1788 callback.onError(new SatelliteException( 1789 SATELLITE_RESULT_REQUEST_FAILED)))); 1790 } 1791 } else { 1792 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1793 callback.onError(new SatelliteException(resultCode)))); 1794 } 1795 } 1796 }; 1797 telephony.requestIsCommunicationAllowedForCurrentLocation(mSubId, receiver); 1798 } else { 1799 loge("requestIsCommunicationAllowedForCurrentLocation() invalid telephony"); 1800 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 1801 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 1802 } 1803 } catch (RemoteException ex) { 1804 loge("requestIsCommunicationAllowedForCurrentLocation() RemoteException: " + ex); 1805 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 1806 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 1807 } 1808 } 1809 1810 /** 1811 * Request to get the duration in seconds after which the satellite will be visible. 1812 * This will be {@link Duration#ZERO} if the satellite is currently visible. 1813 * 1814 * @param executor The executor on which the callback will be called. 1815 * @param callback The callback object to which the result will be delivered. 1816 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 1817 * will return the time after which the satellite will be visible. 1818 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 1819 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 1820 * 1821 * @throws SecurityException if the caller doesn't have required permission. 1822 */ 1823 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1824 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) requestTimeForNextSatelliteVisibility(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<Duration, SatelliteException> callback)1825 public void requestTimeForNextSatelliteVisibility(@NonNull @CallbackExecutor Executor executor, 1826 @NonNull OutcomeReceiver<Duration, SatelliteException> callback) { 1827 Objects.requireNonNull(executor); 1828 Objects.requireNonNull(callback); 1829 1830 try { 1831 ITelephony telephony = getITelephony(); 1832 if (telephony != null) { 1833 ResultReceiver receiver = new ResultReceiver(null) { 1834 @Override 1835 protected void onReceiveResult(int resultCode, Bundle resultData) { 1836 if (resultCode == SATELLITE_RESULT_SUCCESS) { 1837 if (resultData.containsKey(KEY_SATELLITE_NEXT_VISIBILITY)) { 1838 int nextVisibilityDuration = 1839 resultData.getInt(KEY_SATELLITE_NEXT_VISIBILITY); 1840 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1841 callback.onResult( 1842 Duration.ofSeconds(nextVisibilityDuration)))); 1843 } else { 1844 loge("KEY_SATELLITE_NEXT_VISIBILITY does not exist."); 1845 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1846 callback.onError(new SatelliteException( 1847 SATELLITE_RESULT_REQUEST_FAILED)))); 1848 } 1849 } else { 1850 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 1851 callback.onError(new SatelliteException(resultCode)))); 1852 } 1853 } 1854 }; 1855 telephony.requestTimeForNextSatelliteVisibility(mSubId, receiver); 1856 } else { 1857 loge("requestTimeForNextSatelliteVisibility() invalid telephony"); 1858 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 1859 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 1860 } 1861 } catch (RemoteException ex) { 1862 loge("requestTimeForNextSatelliteVisibility() RemoteException: " + ex); 1863 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 1864 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 1865 } 1866 } 1867 1868 /** 1869 * Inform whether the device is aligned with the satellite for demo mode. 1870 * 1871 * Framework can send datagram to modem only when device is aligned with the satellite. 1872 * This method helps framework to simulate the experience of sending datagram over satellite. 1873 * 1874 * @param isAligned {@true} Device is aligned with the satellite for demo mode 1875 * {@false} Device is not aligned with the satellite for demo mode 1876 * 1877 * @throws SecurityException if the caller doesn't have required permission. 1878 * @throws IllegalStateException if the Telephony process is not currently available. 1879 */ 1880 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1881 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) setDeviceAlignedWithSatellite(boolean isAligned)1882 public void setDeviceAlignedWithSatellite(boolean isAligned) { 1883 try { 1884 ITelephony telephony = getITelephony(); 1885 if (telephony != null) { 1886 telephony.setDeviceAlignedWithSatellite(mSubId, isAligned); 1887 } else { 1888 throw new IllegalStateException("telephony service is null."); 1889 } 1890 } catch (RemoteException ex) { 1891 loge("setDeviceAlignedWithSatellite() RemoteException:" + ex); 1892 ex.rethrowAsRuntimeException(); 1893 } 1894 } 1895 1896 /** 1897 * User request to enable or disable carrier supported satellite plmn scan and attach by modem. 1898 * <p> 1899 * This API should be called by only settings app to pass down the user input for 1900 * enabling/disabling satellite. This user input will be persisted across device reboots. 1901 * <p> 1902 * Satellite will be enabled only when the following conditions are met: 1903 * <ul> 1904 * <li>Users want to enable it.</li> 1905 * <li>There is no satellite communication restriction, which is added by 1906 * {@link #addAttachRestrictionForCarrier(int, int, Executor, Consumer)}</li> 1907 * <li>The carrier config {@link 1908 * android.telephony.CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} is set to 1909 * {@code true}.</li> 1910 * </ul> 1911 * 1912 * @param subId The subscription ID of the carrier. 1913 * @param enableSatellite {@code true} to enable the satellite and {@code false} to disable. 1914 * @param executor The executor on which the error code listener will be called. 1915 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 1916 * 1917 * @throws SecurityException if the caller doesn't have required permission. 1918 * @throws IllegalArgumentException if the subscription is invalid. 1919 */ 1920 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1921 @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) requestAttachEnabledForCarrier(int subId, boolean enableSatellite, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)1922 public void requestAttachEnabledForCarrier(int subId, boolean enableSatellite, 1923 @NonNull @CallbackExecutor Executor executor, 1924 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 1925 Objects.requireNonNull(executor); 1926 Objects.requireNonNull(resultListener); 1927 1928 if (enableSatellite) { 1929 removeAttachRestrictionForCarrier(subId, 1930 SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, executor, resultListener); 1931 } else { 1932 addAttachRestrictionForCarrier(subId, 1933 SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, executor, resultListener); 1934 } 1935 } 1936 1937 /** 1938 * Request to get whether the carrier supported satellite plmn scan and attach by modem is 1939 * enabled by user. 1940 * 1941 * @param subId The subscription ID of the carrier. 1942 * @param executor The executor on which the callback will be called. 1943 * @param callback The callback object to which the result will be delivered. 1944 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 1945 * will return a {@code boolean} with value {@code true} if the satellite 1946 * is enabled and {@code false} otherwise. 1947 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 1948 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 1949 * 1950 * @throws SecurityException if the caller doesn't have required permission. 1951 * @throws IllegalStateException if the Telephony process is not currently available. 1952 * @throws IllegalArgumentException if the subscription is invalid. 1953 */ 1954 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1955 @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) requestIsAttachEnabledForCarrier(int subId, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteException> callback)1956 public void requestIsAttachEnabledForCarrier(int subId, 1957 @NonNull @CallbackExecutor Executor executor, 1958 @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { 1959 Objects.requireNonNull(executor); 1960 Objects.requireNonNull(callback); 1961 1962 Set<Integer> restrictionReason = getAttachRestrictionReasonsForCarrier(subId); 1963 executor.execute(() -> callback.onResult( 1964 !restrictionReason.contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER))); 1965 } 1966 1967 /** 1968 * Add a restriction reason for disallowing carrier supported satellite plmn scan and attach 1969 * by modem. 1970 * 1971 * @param subId The subscription ID of the carrier. 1972 * @param reason Reason for disallowing satellite communication. 1973 * @param executor The executor on which the error code listener will be called. 1974 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 1975 * 1976 * @throws SecurityException if the caller doesn't have required permission. 1977 * @throws IllegalArgumentException if the subscription is invalid. 1978 */ 1979 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 1980 @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) addAttachRestrictionForCarrier(int subId, @SatelliteCommunicationRestrictionReason int reason, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)1981 public void addAttachRestrictionForCarrier(int subId, 1982 @SatelliteCommunicationRestrictionReason int reason, 1983 @NonNull @CallbackExecutor Executor executor, 1984 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 1985 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 1986 throw new IllegalArgumentException("Invalid subscription ID"); 1987 } 1988 1989 try { 1990 ITelephony telephony = getITelephony(); 1991 if (telephony != null) { 1992 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 1993 @Override 1994 public void accept(int result) { 1995 executor.execute(() -> Binder.withCleanCallingIdentity( 1996 () -> resultListener.accept(result))); 1997 } 1998 }; 1999 telephony.addAttachRestrictionForCarrier(subId, reason, errorCallback); 2000 } else { 2001 loge("addAttachRestrictionForCarrier() invalid telephony"); 2002 executor.execute(() -> Binder.withCleanCallingIdentity( 2003 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 2004 } 2005 } catch (RemoteException ex) { 2006 loge("addAttachRestrictionForCarrier() RemoteException:" + ex); 2007 executor.execute(() -> Binder.withCleanCallingIdentity( 2008 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 2009 } 2010 } 2011 2012 /** 2013 * Remove a restriction reason for disallowing carrier supported satellite plmn scan and attach 2014 * by modem. 2015 * 2016 * @param subId The subscription ID of the carrier. 2017 * @param reason Reason for disallowing satellite communication. 2018 * @param executor The executor on which the error code listener will be called. 2019 * @param resultListener Listener for the {@link SatelliteResult} result of the operation. 2020 * 2021 * @throws SecurityException if the caller doesn't have required permission. 2022 * @throws IllegalArgumentException if the subscription is invalid. 2023 */ 2024 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2025 @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) removeAttachRestrictionForCarrier(int subId, @SatelliteCommunicationRestrictionReason int reason, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener)2026 public void removeAttachRestrictionForCarrier(int subId, 2027 @SatelliteCommunicationRestrictionReason int reason, 2028 @NonNull @CallbackExecutor Executor executor, 2029 @SatelliteResult @NonNull Consumer<Integer> resultListener) { 2030 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 2031 throw new IllegalArgumentException("Invalid subscription ID"); 2032 } 2033 2034 try { 2035 ITelephony telephony = getITelephony(); 2036 if (telephony != null) { 2037 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 2038 @Override 2039 public void accept(int result) { 2040 executor.execute(() -> Binder.withCleanCallingIdentity( 2041 () -> resultListener.accept(result))); 2042 } 2043 }; 2044 telephony.removeAttachRestrictionForCarrier(subId, reason, errorCallback); 2045 } else { 2046 loge("removeAttachRestrictionForCarrier() invalid telephony"); 2047 executor.execute(() -> Binder.withCleanCallingIdentity( 2048 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 2049 } 2050 } catch (RemoteException ex) { 2051 loge("removeAttachRestrictionForCarrier() RemoteException:" + ex); 2052 executor.execute(() -> Binder.withCleanCallingIdentity( 2053 () -> resultListener.accept(SATELLITE_RESULT_ILLEGAL_STATE))); 2054 } 2055 } 2056 2057 /** 2058 * Get reasons for disallowing satellite attach, as requested by 2059 * {@link #addAttachRestrictionForCarrier(int, int, Executor, Consumer)} 2060 * 2061 * @param subId The subscription ID of the carrier. 2062 * @return Set of reasons for disallowing satellite communication. 2063 * 2064 * @throws SecurityException if the caller doesn't have required permission. 2065 * @throws IllegalStateException if the Telephony process is not currently available. 2066 * @throws IllegalArgumentException if the subscription is invalid. 2067 */ 2068 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2069 @SatelliteCommunicationRestrictionReason 2070 @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) getAttachRestrictionReasonsForCarrier(int subId)2071 @NonNull public Set<Integer> getAttachRestrictionReasonsForCarrier(int subId) { 2072 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 2073 throw new IllegalArgumentException("Invalid subscription ID"); 2074 } 2075 2076 try { 2077 ITelephony telephony = getITelephony(); 2078 if (telephony != null) { 2079 int[] receivedArray = 2080 telephony.getAttachRestrictionReasonsForCarrier(subId); 2081 if (receivedArray.length == 0) { 2082 logd("receivedArray is empty, create empty set"); 2083 return new HashSet<>(); 2084 } else { 2085 return Arrays.stream(receivedArray).boxed().collect(Collectors.toSet()); 2086 } 2087 } else { 2088 throw new IllegalStateException("Telephony service is null."); 2089 } 2090 } catch (RemoteException ex) { 2091 loge("getAttachRestrictionReasonsForCarrier() RemoteException: " + ex); 2092 ex.rethrowAsRuntimeException(); 2093 } 2094 return new HashSet<>(); 2095 } 2096 2097 /** 2098 * Request to get the signal strength of the satellite connection. 2099 * 2100 * <p> 2101 * Note: This API is specifically designed for OEM enabled satellite connectivity only. 2102 * For satellite connectivity enabled using carrier roaming, please refer to 2103 * {@link android.telephony.TelephonyCallback.SignalStrengthsListener}, and 2104 * {@link TelephonyManager#registerTelephonyCallback(Executor, TelephonyCallback)}. 2105 * </p> 2106 * 2107 * @param executor The executor on which the callback will be called. 2108 * @param callback The callback object to which the result will be delivered. If the request is 2109 * successful, {@link OutcomeReceiver#onResult(Object)} will return an instance of 2110 * {@link NtnSignalStrength} with a value of {@link NtnSignalStrength.NtnSignalStrengthLevel} 2111 * The {@link NtnSignalStrength#NTN_SIGNAL_STRENGTH_NONE} will be returned if there is no 2112 * signal strength data available. 2113 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} will return a 2114 * {@link SatelliteException} with the {@link SatelliteResult}. 2115 * 2116 * @throws SecurityException if the caller doesn't have required permission. 2117 */ 2118 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2119 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) requestNtnSignalStrength(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<NtnSignalStrength, SatelliteException> callback)2120 public void requestNtnSignalStrength(@NonNull @CallbackExecutor Executor executor, 2121 @NonNull OutcomeReceiver<NtnSignalStrength, SatelliteException> callback) { 2122 Objects.requireNonNull(executor); 2123 Objects.requireNonNull(callback); 2124 2125 try { 2126 ITelephony telephony = getITelephony(); 2127 if (telephony != null) { 2128 ResultReceiver receiver = new ResultReceiver(null) { 2129 @Override 2130 protected void onReceiveResult(int resultCode, Bundle resultData) { 2131 if (resultCode == SATELLITE_RESULT_SUCCESS) { 2132 if (resultData.containsKey(KEY_NTN_SIGNAL_STRENGTH)) { 2133 NtnSignalStrength ntnSignalStrength = 2134 resultData.getParcelable(KEY_NTN_SIGNAL_STRENGTH, 2135 NtnSignalStrength.class); 2136 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2137 callback.onResult(ntnSignalStrength))); 2138 } else { 2139 loge("KEY_NTN_SIGNAL_STRENGTH does not exist."); 2140 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2141 callback.onError(new SatelliteException( 2142 SATELLITE_RESULT_REQUEST_FAILED)))); 2143 } 2144 } else { 2145 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2146 callback.onError(new SatelliteException(resultCode)))); 2147 } 2148 } 2149 }; 2150 telephony.requestNtnSignalStrength(mSubId, receiver); 2151 } else { 2152 loge("requestNtnSignalStrength() invalid telephony"); 2153 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 2154 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 2155 } 2156 } catch (RemoteException ex) { 2157 loge("requestNtnSignalStrength() RemoteException: " + ex); 2158 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 2159 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 2160 } 2161 } 2162 2163 /** 2164 * Registers for NTN signal strength changed from satellite modem. 2165 * If the registration operation is not successful, a {@link SatelliteException} that contains 2166 * {@link SatelliteResult} will be thrown. 2167 * 2168 * <p> 2169 * Note: This API is specifically designed for OEM enabled satellite connectivity only. 2170 * For satellite connectivity enabled using carrier roaming, please refer to 2171 * {@link android.telephony.TelephonyCallback.SignalStrengthsListener}, and 2172 * {@link TelephonyManager#registerTelephonyCallback(Executor, TelephonyCallback)}. 2173 * </p> 2174 * 2175 * @param executor The executor on which the callback will be called. 2176 * @param callback The callback to handle the NTN signal strength changed event. 2177 * 2178 * @throws SecurityException if the caller doesn't have required permission. 2179 * @throws IllegalStateException if the Telephony process is not currently available. 2180 */ 2181 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2182 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) registerForNtnSignalStrengthChanged(@onNull @allbackExecutor Executor executor, @NonNull NtnSignalStrengthCallback callback)2183 public void registerForNtnSignalStrengthChanged(@NonNull @CallbackExecutor Executor executor, 2184 @NonNull NtnSignalStrengthCallback callback) { 2185 Objects.requireNonNull(executor); 2186 Objects.requireNonNull(callback); 2187 2188 try { 2189 ITelephony telephony = getITelephony(); 2190 if (telephony != null) { 2191 INtnSignalStrengthCallback internalCallback = 2192 new INtnSignalStrengthCallback.Stub() { 2193 @Override 2194 public void onNtnSignalStrengthChanged( 2195 NtnSignalStrength ntnSignalStrength) { 2196 executor.execute(() -> Binder.withCleanCallingIdentity( 2197 () -> callback.onNtnSignalStrengthChanged( 2198 ntnSignalStrength))); 2199 } 2200 }; 2201 telephony.registerForNtnSignalStrengthChanged(mSubId, internalCallback); 2202 sNtnSignalStrengthCallbackMap.put(callback, internalCallback); 2203 } else { 2204 throw new IllegalStateException("Telephony service is null."); 2205 } 2206 } catch (RemoteException ex) { 2207 loge("registerForNtnSignalStrengthChanged() RemoteException: " + ex); 2208 ex.rethrowAsRuntimeException(); 2209 } 2210 } 2211 2212 /** 2213 * Unregisters for NTN signal strength changed from satellite modem. 2214 * If callback was not registered before, the request will be ignored. 2215 * 2216 * <p> 2217 * Note: This API is specifically designed for OEM enabled satellite connectivity only. 2218 * For satellite connectivity enabled using carrier roaming, please refer to 2219 * {@link TelephonyManager#unregisterTelephonyCallback(TelephonyCallback)}.. 2220 * </p> 2221 * 2222 * @param callback The callback that was passed to. 2223 * {@link #registerForNtnSignalStrengthChanged(Executor, NtnSignalStrengthCallback)}. 2224 * 2225 * @throws SecurityException if the caller doesn't have required permission. 2226 * @throws IllegalArgumentException if the callback is not valid or has already been 2227 * unregistered. 2228 * @throws IllegalStateException if the Telephony process is not currently available. 2229 */ 2230 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2231 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) unregisterForNtnSignalStrengthChanged(@onNull NtnSignalStrengthCallback callback)2232 public void unregisterForNtnSignalStrengthChanged(@NonNull NtnSignalStrengthCallback callback) { 2233 Objects.requireNonNull(callback); 2234 INtnSignalStrengthCallback internalCallback = 2235 sNtnSignalStrengthCallbackMap.remove(callback); 2236 2237 try { 2238 ITelephony telephony = getITelephony(); 2239 if (telephony != null) { 2240 if (internalCallback != null) { 2241 telephony.unregisterForNtnSignalStrengthChanged(mSubId, internalCallback); 2242 } else { 2243 loge("unregisterForNtnSignalStrengthChanged: No internal callback."); 2244 throw new IllegalArgumentException("callback is not valid"); 2245 } 2246 } else { 2247 throw new IllegalStateException("Telephony service is null."); 2248 } 2249 } catch (RemoteException ex) { 2250 loge("unregisterForNtnSignalStrengthChanged() RemoteException: " + ex); 2251 ex.rethrowAsRuntimeException(); 2252 } 2253 } 2254 2255 /** 2256 * Registers for satellite capabilities change event from the satellite service. 2257 * 2258 * @param executor The executor on which the callback will be called. 2259 * @param callback The callback to handle the satellite capabilities changed event. 2260 * 2261 * @throws SecurityException if the caller doesn't have required permission. 2262 * @throws IllegalStateException if the Telephony process is not currently available. 2263 */ 2264 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2265 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) registerForCapabilitiesChanged( @onNull @allbackExecutor Executor executor, @NonNull SatelliteCapabilitiesCallback callback)2266 @SatelliteResult public int registerForCapabilitiesChanged( 2267 @NonNull @CallbackExecutor Executor executor, 2268 @NonNull SatelliteCapabilitiesCallback callback) { 2269 Objects.requireNonNull(executor); 2270 Objects.requireNonNull(callback); 2271 2272 try { 2273 ITelephony telephony = getITelephony(); 2274 if (telephony != null) { 2275 ISatelliteCapabilitiesCallback internalCallback = 2276 new ISatelliteCapabilitiesCallback.Stub() { 2277 @Override 2278 public void onSatelliteCapabilitiesChanged( 2279 SatelliteCapabilities capabilities) { 2280 executor.execute(() -> Binder.withCleanCallingIdentity( 2281 () -> callback.onSatelliteCapabilitiesChanged( 2282 capabilities))); 2283 } 2284 }; 2285 sSatelliteCapabilitiesCallbackMap.put(callback, internalCallback); 2286 return telephony.registerForCapabilitiesChanged(mSubId, internalCallback); 2287 } else { 2288 throw new IllegalStateException("Telephony service is null."); 2289 } 2290 } catch (RemoteException ex) { 2291 loge("registerForCapabilitiesChanged() RemoteException: " + ex); 2292 ex.rethrowAsRuntimeException(); 2293 } 2294 return SATELLITE_RESULT_REQUEST_FAILED; 2295 } 2296 2297 /** 2298 * Unregisters for satellite capabilities change event from the satellite service. 2299 * If callback was not registered before, the request will be ignored. 2300 * 2301 * @param callback The callback that was passed to. 2302 * {@link #registerForCapabilitiesChanged(Executor, SatelliteCapabilitiesCallback)}. 2303 * 2304 * @throws SecurityException if the caller doesn't have required permission. 2305 * @throws IllegalStateException if the Telephony process is not currently available. 2306 */ 2307 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2308 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) unregisterForCapabilitiesChanged( @onNull SatelliteCapabilitiesCallback callback)2309 public void unregisterForCapabilitiesChanged( 2310 @NonNull SatelliteCapabilitiesCallback callback) { 2311 Objects.requireNonNull(callback); 2312 ISatelliteCapabilitiesCallback internalCallback = 2313 sSatelliteCapabilitiesCallbackMap.remove(callback); 2314 2315 try { 2316 ITelephony telephony = getITelephony(); 2317 if (telephony != null) { 2318 if (internalCallback != null) { 2319 telephony.unregisterForCapabilitiesChanged(mSubId, internalCallback); 2320 } else { 2321 loge("unregisterForCapabilitiesChanged: No internal callback."); 2322 } 2323 } else { 2324 throw new IllegalStateException("Telephony service is null."); 2325 } 2326 } catch (RemoteException ex) { 2327 loge("unregisterForCapabilitiesChanged() RemoteException: " + ex); 2328 ex.rethrowAsRuntimeException(); 2329 } 2330 } 2331 2332 /** 2333 * Get all satellite PLMNs for which attach is enable for carrier. 2334 * 2335 * @param subId subId The subscription ID of the carrier. 2336 * 2337 * @return List of plmn for carrier satellite service. If no plmn is available, empty list will 2338 * be returned. 2339 */ 2340 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2341 @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) getSatellitePlmnsForCarrier(int subId)2342 @NonNull public List<String> getSatellitePlmnsForCarrier(int subId) { 2343 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 2344 throw new IllegalArgumentException("Invalid subscription ID"); 2345 } 2346 2347 try { 2348 ITelephony telephony = getITelephony(); 2349 if (telephony != null) { 2350 return telephony.getSatellitePlmnsForCarrier(subId); 2351 } else { 2352 throw new IllegalStateException("Telephony service is null."); 2353 } 2354 } catch (RemoteException ex) { 2355 loge("getSatellitePlmnsForCarrier() RemoteException: " + ex); 2356 ex.rethrowAsRuntimeException(); 2357 } 2358 return new ArrayList<>(); 2359 } 2360 2361 /** 2362 * Registers for the satellite supported state changed. 2363 * 2364 * @param executor The executor on which the callback will be called. 2365 * @param callback The callback to handle the satellite supoprted state changed event. 2366 * 2367 * @return The {@link SatelliteResult} result of the operation. 2368 * 2369 * @throws SecurityException if the caller doesn't have required permission. 2370 * @throws IllegalStateException if the Telephony process is not currently available. 2371 * 2372 * @hide 2373 */ 2374 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) registerForSupportedStateChanged( @onNull @allbackExecutor Executor executor, @NonNull SatelliteSupportedStateCallback callback)2375 @SatelliteResult public int registerForSupportedStateChanged( 2376 @NonNull @CallbackExecutor Executor executor, 2377 @NonNull SatelliteSupportedStateCallback callback) { 2378 Objects.requireNonNull(executor); 2379 Objects.requireNonNull(callback); 2380 2381 try { 2382 ITelephony telephony = getITelephony(); 2383 if (telephony != null) { 2384 ISatelliteSupportedStateCallback internalCallback = 2385 new ISatelliteSupportedStateCallback.Stub() { 2386 @Override 2387 public void onSatelliteSupportedStateChanged(boolean supported) { 2388 executor.execute(() -> Binder.withCleanCallingIdentity( 2389 () -> callback.onSatelliteSupportedStateChanged( 2390 supported))); 2391 } 2392 }; 2393 sSatelliteSupportedStateCallbackMap.put(callback, internalCallback); 2394 return telephony.registerForSatelliteSupportedStateChanged( 2395 mSubId, internalCallback); 2396 } else { 2397 throw new IllegalStateException("telephony service is null."); 2398 } 2399 } catch (RemoteException ex) { 2400 loge("registerForSupportedStateChanged() RemoteException: " + ex); 2401 ex.rethrowAsRuntimeException(); 2402 } 2403 return SATELLITE_RESULT_REQUEST_FAILED; 2404 } 2405 2406 /** 2407 * Unregisters for the satellite supported state changed. 2408 * If callback was not registered before, the request will be ignored. 2409 * 2410 * @param callback The callback that was passed to 2411 * {@link #registerForSupportedStateChanged(Executor, SatelliteSupportedStateCallback)} 2412 * 2413 * @throws SecurityException if the caller doesn't have required permission. 2414 * @throws IllegalStateException if the Telephony process is not currently available. 2415 * 2416 * @hide 2417 */ 2418 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2419 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) unregisterForSupportedStateChanged( @onNull SatelliteSupportedStateCallback callback)2420 public void unregisterForSupportedStateChanged( 2421 @NonNull SatelliteSupportedStateCallback callback) { 2422 Objects.requireNonNull(callback); 2423 ISatelliteSupportedStateCallback internalCallback = 2424 sSatelliteSupportedStateCallbackMap.remove(callback); 2425 2426 try { 2427 ITelephony telephony = getITelephony(); 2428 if (telephony != null) { 2429 if (internalCallback != null) { 2430 telephony.unregisterForSatelliteSupportedStateChanged(mSubId, internalCallback); 2431 } else { 2432 loge("unregisterForSupportedStateChanged: No internal callback."); 2433 } 2434 } else { 2435 throw new IllegalStateException("telephony service is null."); 2436 } 2437 } catch (RemoteException ex) { 2438 loge("unregisterForSupportedStateChanged() RemoteException: " + ex); 2439 ex.rethrowAsRuntimeException(); 2440 } 2441 } 2442 2443 /** 2444 * Registers for the satellite communication allowed state changed. 2445 * 2446 * @param executor The executor on which the callback will be called. 2447 * @param callback The callback to handle satellite communication allowed state changed event. 2448 * @return The {@link SatelliteResult} result of the operation. 2449 * @throws SecurityException if the caller doesn't have required permission. 2450 * @throws IllegalStateException if the Telephony process is not currently available. 2451 * @hide 2452 */ 2453 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2454 @SatelliteResult registerForCommunicationAllowedStateChanged( @onNull @allbackExecutor Executor executor, @NonNull SatelliteCommunicationAllowedStateCallback callback)2455 public int registerForCommunicationAllowedStateChanged( 2456 @NonNull @CallbackExecutor Executor executor, 2457 @NonNull SatelliteCommunicationAllowedStateCallback callback) { 2458 Objects.requireNonNull(executor); 2459 Objects.requireNonNull(callback); 2460 2461 try { 2462 ITelephony telephony = getITelephony(); 2463 if (telephony != null) { 2464 ISatelliteCommunicationAllowedStateCallback internalCallback = 2465 new ISatelliteCommunicationAllowedStateCallback.Stub() { 2466 @Override 2467 public void onSatelliteCommunicationAllowedStateChanged( 2468 boolean isAllowed) { 2469 executor.execute(() -> Binder.withCleanCallingIdentity( 2470 () -> callback.onSatelliteCommunicationAllowedStateChanged( 2471 isAllowed))); 2472 } 2473 }; 2474 sSatelliteCommunicationAllowedStateCallbackMap.put(callback, internalCallback); 2475 return telephony.registerForCommunicationAllowedStateChanged( 2476 mSubId, internalCallback); 2477 } else { 2478 throw new IllegalStateException("telephony service is null."); 2479 } 2480 } catch (RemoteException ex) { 2481 loge("registerForCommunicationAllowedStateChanged() RemoteException: " + ex); 2482 ex.rethrowAsRuntimeException(); 2483 } 2484 return SATELLITE_RESULT_REQUEST_FAILED; 2485 } 2486 2487 /** 2488 * Unregisters for the satellite communication allowed state changed. 2489 * If callback was not registered before, the request will be ignored. 2490 * 2491 * @param callback The callback that was passed to 2492 * {@link #registerForCommunicationAllowedStateChanged(Executor, 2493 * SatelliteCommunicationAllowedStateCallback)} 2494 * @throws SecurityException if the caller doesn't have required permission. 2495 * @throws IllegalStateException if the Telephony process is not currently available. 2496 * @hide 2497 */ 2498 @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) 2499 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) unregisterForCommunicationAllowedStateChanged( @onNull SatelliteCommunicationAllowedStateCallback callback)2500 public void unregisterForCommunicationAllowedStateChanged( 2501 @NonNull SatelliteCommunicationAllowedStateCallback callback) { 2502 Objects.requireNonNull(callback); 2503 ISatelliteCommunicationAllowedStateCallback internalCallback = 2504 sSatelliteCommunicationAllowedStateCallbackMap.remove(callback); 2505 2506 try { 2507 ITelephony telephony = getITelephony(); 2508 if (telephony != null) { 2509 if (internalCallback != null) { 2510 telephony.unregisterForCommunicationAllowedStateChanged(mSubId, 2511 internalCallback); 2512 } else { 2513 loge("unregisterForCommunicationAllowedStateChanged: No internal callback."); 2514 } 2515 } else { 2516 throw new IllegalStateException("telephony service is null."); 2517 } 2518 } catch (RemoteException ex) { 2519 loge("unregisterForCommunicationAllowedStateChanged() RemoteException: " + ex); 2520 ex.rethrowAsRuntimeException(); 2521 } 2522 } 2523 2524 /** 2525 * Request to get the {@link SatelliteSessionStats} of the satellite service. 2526 * 2527 * @param executor The executor on which the callback will be called. 2528 * @param callback The callback object to which the result will be delivered. 2529 * If the request is successful, {@link OutcomeReceiver#onResult(Object)} 2530 * will return the {@link SatelliteSessionStats} of the satellite service. 2531 * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} 2532 * will return a {@link SatelliteException} with the {@link SatelliteResult}. 2533 * 2534 * @throws SecurityException if the caller doesn't have required permission. 2535 * @hide 2536 */ 2537 @RequiresPermission(allOf = {Manifest.permission.PACKAGE_USAGE_STATS, 2538 Manifest.permission.MODIFY_PHONE_STATE}) 2539 @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) requestSessionStats(@onNull @allbackExecutor Executor executor, @NonNull OutcomeReceiver<SatelliteSessionStats, SatelliteException> callback)2540 public void requestSessionStats(@NonNull @CallbackExecutor Executor executor, 2541 @NonNull OutcomeReceiver<SatelliteSessionStats, SatelliteException> callback) { 2542 Objects.requireNonNull(executor); 2543 Objects.requireNonNull(callback); 2544 2545 try { 2546 ITelephony telephony = getITelephony(); 2547 if (telephony != null) { 2548 ResultReceiver receiver = new ResultReceiver(null) { 2549 @Override 2550 protected void onReceiveResult(int resultCode, Bundle resultData) { 2551 if (resultCode == SATELLITE_RESULT_SUCCESS) { 2552 if (resultData.containsKey(KEY_SESSION_STATS)) { 2553 SatelliteSessionStats stats = 2554 resultData.getParcelable(KEY_SESSION_STATS, 2555 SatelliteSessionStats.class); 2556 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2557 callback.onResult(stats))); 2558 } else { 2559 loge("KEY_SESSION_STATS does not exist."); 2560 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2561 callback.onError(new SatelliteException( 2562 SATELLITE_RESULT_REQUEST_FAILED)))); 2563 } 2564 } else { 2565 executor.execute(() -> Binder.withCleanCallingIdentity(() -> 2566 callback.onError(new SatelliteException(resultCode)))); 2567 } 2568 } 2569 }; 2570 telephony.requestSatelliteSessionStats(mSubId, receiver); 2571 } else { 2572 loge("requestSessionStats() invalid telephony"); 2573 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 2574 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 2575 } 2576 } catch (RemoteException ex) { 2577 loge("requestSessionStats() RemoteException: " + ex); 2578 executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( 2579 new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); 2580 } 2581 } 2582 2583 @Nullable getITelephony()2584 private static ITelephony getITelephony() { 2585 ITelephony binder = ITelephony.Stub.asInterface(TelephonyFrameworkInitializer 2586 .getTelephonyServiceManager() 2587 .getTelephonyServiceRegisterer() 2588 .get()); 2589 return binder; 2590 } 2591 logd(@onNull String log)2592 private static void logd(@NonNull String log) { 2593 Rlog.d(TAG, log); 2594 } 2595 loge(@onNull String log)2596 private static void loge(@NonNull String log) { 2597 Rlog.e(TAG, log); 2598 } 2599 } 2600