1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony.satellite; 18 19 import static android.provider.Settings.ACTION_SATELLITE_SETTING; 20 import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY; 21 import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE; 22 import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT; 23 import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL; 24 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL; 25 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT; 26 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL; 27 import static android.telephony.SubscriptionManager.SATELLITE_ATTACH_ENABLED_FOR_CARRIER; 28 import static android.telephony.SubscriptionManager.SATELLITE_ENTITLEMENT_STATUS; 29 import static android.telephony.SubscriptionManager.isValidSubscriptionId; 30 import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE; 31 import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS; 32 import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911; 33 import static android.telephony.satellite.SatelliteManager.KEY_NTN_SIGNAL_STRENGTH; 34 import static android.telephony.satellite.SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT; 35 import static android.telephony.satellite.SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER; 36 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT; 37 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED; 38 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS; 39 40 import static com.android.internal.telephony.configupdate.ConfigProviderAdaptor.DOMAIN_SATELLITE; 41 42 import android.annotation.ArrayRes; 43 import android.annotation.NonNull; 44 import android.annotation.Nullable; 45 import android.app.Notification; 46 import android.app.NotificationChannel; 47 import android.app.NotificationManager; 48 import android.app.PendingIntent; 49 import android.bluetooth.BluetoothAdapter; 50 import android.content.BroadcastReceiver; 51 import android.content.ContentResolver; 52 import android.content.Context; 53 import android.content.Intent; 54 import android.content.IntentFilter; 55 import android.content.SharedPreferences; 56 import android.content.pm.PackageManager; 57 import android.content.res.Resources; 58 import android.database.ContentObserver; 59 import android.net.Uri; 60 import android.net.wifi.WifiManager; 61 import android.nfc.NfcAdapter; 62 import android.os.AsyncResult; 63 import android.os.Binder; 64 import android.os.Build; 65 import android.os.Bundle; 66 import android.os.CancellationSignal; 67 import android.os.Handler; 68 import android.os.HandlerExecutor; 69 import android.os.HandlerThread; 70 import android.os.IBinder; 71 import android.os.ICancellationSignal; 72 import android.os.Looper; 73 import android.os.Message; 74 import android.os.PersistableBundle; 75 import android.os.Registrant; 76 import android.os.RegistrantList; 77 import android.os.RemoteException; 78 import android.os.ResultReceiver; 79 import android.os.ServiceSpecificException; 80 import android.os.SystemClock; 81 import android.os.SystemProperties; 82 import android.os.UserHandle; 83 import android.provider.Settings; 84 import android.provider.Telephony; 85 import android.telephony.AccessNetworkConstants; 86 import android.telephony.CarrierConfigManager; 87 import android.telephony.DropBoxManagerLoggerBackend; 88 import android.telephony.NetworkRegistrationInfo; 89 import android.telephony.PersistentLogger; 90 import android.telephony.Rlog; 91 import android.telephony.ServiceState; 92 import android.telephony.SubscriptionManager; 93 import android.telephony.TelephonyManager; 94 import android.telephony.satellite.INtnSignalStrengthCallback; 95 import android.telephony.satellite.ISatelliteCapabilitiesCallback; 96 import android.telephony.satellite.ISatelliteDatagramCallback; 97 import android.telephony.satellite.ISatelliteModemStateCallback; 98 import android.telephony.satellite.ISatelliteProvisionStateCallback; 99 import android.telephony.satellite.ISatelliteSupportedStateCallback; 100 import android.telephony.satellite.ISatelliteTransmissionUpdateCallback; 101 import android.telephony.satellite.NtnSignalStrength; 102 import android.telephony.satellite.SatelliteCapabilities; 103 import android.telephony.satellite.SatelliteDatagram; 104 import android.telephony.satellite.SatelliteManager; 105 import android.util.Log; 106 import android.util.Pair; 107 import android.util.SparseArray; 108 import android.util.SparseBooleanArray; 109 import android.uwb.UwbManager; 110 111 import com.android.internal.R; 112 import com.android.internal.annotations.GuardedBy; 113 import com.android.internal.annotations.VisibleForTesting; 114 import com.android.internal.telephony.CommandsInterface; 115 import com.android.internal.telephony.DeviceStateMonitor; 116 import com.android.internal.telephony.IIntegerConsumer; 117 import com.android.internal.telephony.Phone; 118 import com.android.internal.telephony.PhoneFactory; 119 import com.android.internal.telephony.configupdate.ConfigParser; 120 import com.android.internal.telephony.configupdate.ConfigProviderAdaptor; 121 import com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver; 122 import com.android.internal.telephony.flags.FeatureFlags; 123 import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteControllerStats; 124 import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteSessionStats; 125 import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats; 126 import com.android.internal.telephony.satellite.metrics.ProvisionMetricsStats; 127 import com.android.internal.telephony.satellite.metrics.SessionMetricsStats; 128 import com.android.internal.telephony.subscription.SubscriptionManagerService; 129 import com.android.internal.telephony.util.TelephonyUtils; 130 import com.android.internal.util.FunctionalUtils; 131 132 import java.util.ArrayList; 133 import java.util.Arrays; 134 import java.util.Collections; 135 import java.util.HashMap; 136 import java.util.HashSet; 137 import java.util.List; 138 import java.util.Map; 139 import java.util.Optional; 140 import java.util.Set; 141 import java.util.concurrent.ConcurrentHashMap; 142 import java.util.concurrent.Executors; 143 import java.util.concurrent.TimeUnit; 144 import java.util.concurrent.atomic.AtomicBoolean; 145 import java.util.concurrent.atomic.AtomicLong; 146 import java.util.function.Consumer; 147 import java.util.stream.Collectors; 148 149 /** 150 * Satellite controller is the backend service of 151 * {@link android.telephony.satellite.SatelliteManager}. 152 */ 153 public class SatelliteController extends Handler { 154 private static final String TAG = "SatelliteController"; 155 /** Whether enabling verbose debugging message or not. */ 156 private static final boolean DBG = false; 157 private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem"; 158 private static final boolean DEBUG = !"user".equals(Build.TYPE); 159 /** File used to store shared preferences related to satellite. */ 160 public static final String SATELLITE_SHARED_PREF = "satellite_shared_pref"; 161 public static final String SATELLITE_SUBSCRIPTION_ID = "satellite_subscription_id"; 162 /** Value to pass for the setting key SATELLITE_MODE_ENABLED, enabled = 1, disabled = 0 */ 163 public static final int SATELLITE_MODE_ENABLED_TRUE = 1; 164 public static final int SATELLITE_MODE_ENABLED_FALSE = 0; 165 public static final int INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE = -1; 166 /** 167 * This is used by CTS to override the timeout duration to wait for the response of the request 168 * to enable satellite. 169 */ 170 public static final int TIMEOUT_TYPE_WAIT_FOR_SATELLITE_ENABLING_RESPONSE = 1; 171 /** This is used by CTS to override demo pointing aligned duration. */ 172 public static final int TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS = 2; 173 /** This is used by CTS to override demo pointing not aligned duration. */ 174 public static final int TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS = 3; 175 176 /** Key used to read/write OEM-enabled satellite provision status in shared preferences. */ 177 private static final String OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY = 178 "oem_enabled_satellite_provision_status_key"; 179 180 public static final long DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS = 181 TimeUnit.SECONDS.toMillis(30); 182 183 /** Message codes used in handleMessage() */ 184 //TODO: Move the Commands and events related to position updates to PointingAppController 185 private static final int CMD_START_SATELLITE_TRANSMISSION_UPDATES = 1; 186 private static final int EVENT_START_SATELLITE_TRANSMISSION_UPDATES_DONE = 2; 187 private static final int CMD_STOP_SATELLITE_TRANSMISSION_UPDATES = 3; 188 private static final int EVENT_STOP_SATELLITE_TRANSMISSION_UPDATES_DONE = 4; 189 private static final int CMD_PROVISION_SATELLITE_SERVICE = 7; 190 private static final int EVENT_PROVISION_SATELLITE_SERVICE_DONE = 8; 191 private static final int CMD_DEPROVISION_SATELLITE_SERVICE = 9; 192 private static final int EVENT_DEPROVISION_SATELLITE_SERVICE_DONE = 10; 193 private static final int CMD_SET_SATELLITE_ENABLED = 11; 194 private static final int EVENT_SET_SATELLITE_ENABLED_DONE = 12; 195 private static final int CMD_IS_SATELLITE_ENABLED = 13; 196 private static final int EVENT_IS_SATELLITE_ENABLED_DONE = 14; 197 private static final int CMD_IS_SATELLITE_SUPPORTED = 15; 198 private static final int EVENT_IS_SATELLITE_SUPPORTED_DONE = 16; 199 private static final int CMD_GET_SATELLITE_CAPABILITIES = 17; 200 private static final int EVENT_GET_SATELLITE_CAPABILITIES_DONE = 18; 201 private static final int CMD_GET_TIME_SATELLITE_NEXT_VISIBLE = 21; 202 private static final int EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE = 22; 203 private static final int EVENT_RADIO_STATE_CHANGED = 23; 204 private static final int CMD_IS_SATELLITE_PROVISIONED = 24; 205 private static final int EVENT_IS_SATELLITE_PROVISIONED_DONE = 25; 206 private static final int EVENT_SATELLITE_PROVISION_STATE_CHANGED = 26; 207 private static final int EVENT_PENDING_DATAGRAMS = 27; 208 private static final int EVENT_SATELLITE_MODEM_STATE_CHANGED = 28; 209 private static final int EVENT_SET_SATELLITE_PLMN_INFO_DONE = 29; 210 private static final int CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE = 30; 211 private static final int EVENT_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE_DONE = 31; 212 private static final int CMD_REQUEST_NTN_SIGNAL_STRENGTH = 32; 213 private static final int EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE = 33; 214 private static final int EVENT_NTN_SIGNAL_STRENGTH_CHANGED = 34; 215 private static final int CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING = 35; 216 private static final int EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE = 36; 217 private static final int EVENT_SERVICE_STATE_CHANGED = 37; 218 private static final int EVENT_SATELLITE_CAPABILITIES_CHANGED = 38; 219 private static final int EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT = 39; 220 private static final int EVENT_SATELLITE_CONFIG_DATA_UPDATED = 40; 221 private static final int EVENT_SATELLITE_SUPPORTED_STATE_CHANGED = 41; 222 private static final int EVENT_NOTIFY_NTN_HYSTERESIS_TIMED_OUT = 42; 223 224 @NonNull private static SatelliteController sInstance; 225 @NonNull private final Context mContext; 226 @NonNull private final SatelliteModemInterface mSatelliteModemInterface; 227 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 228 @NonNull protected SatelliteSessionController mSatelliteSessionController; 229 @NonNull private final PointingAppController mPointingAppController; 230 @NonNull private final DatagramController mDatagramController; 231 @NonNull private final ControllerMetricsStats mControllerMetricsStats; 232 @NonNull private final ProvisionMetricsStats mProvisionMetricsStats; 233 @NonNull private SessionMetricsStats mSessionMetricsStats; 234 @NonNull private CarrierRoamingSatelliteControllerStats mCarrierRoamingSatelliteControllerStats; 235 @NonNull private final SubscriptionManagerService mSubscriptionManagerService; 236 private final CommandsInterface mCi; 237 private ContentResolver mContentResolver; 238 private final DeviceStateMonitor mDSM; 239 240 private final Object mRadioStateLock = new Object(); 241 242 /** Flags to indicate whether the respective radio is enabled */ 243 @GuardedBy("mRadioStateLock") 244 private boolean mBTStateEnabled = false; 245 @GuardedBy("mRadioStateLock") 246 private boolean mNfcStateEnabled = false; 247 @GuardedBy("mRadioStateLock") 248 private boolean mUwbStateEnabled = false; 249 @GuardedBy("mRadioStateLock") 250 private boolean mWifiStateEnabled = false; 251 252 // Flags to indicate that respective radios need to be disabled when satellite is enabled 253 private boolean mDisableBTOnSatelliteEnabled = false; 254 private boolean mDisableNFCOnSatelliteEnabled = false; 255 private boolean mDisableUWBOnSatelliteEnabled = false; 256 private boolean mDisableWifiOnSatelliteEnabled = false; 257 258 private final Object mSatelliteEnabledRequestLock = new Object(); 259 @GuardedBy("mSatelliteEnabledRequestLock") 260 private RequestSatelliteEnabledArgument mSatelliteEnabledRequest = null; 261 /** Flag to indicate that satellite is enabled successfully 262 * and waiting for all the radios to be disabled so that success can be sent to callback 263 */ 264 @GuardedBy("mSatelliteEnabledRequestLock") 265 private boolean mWaitingForRadioDisabled = false; 266 267 private boolean mWaitingForDisableSatelliteModemResponse = false; 268 private boolean mWaitingForSatelliteModemOff = false; 269 270 private final AtomicBoolean mRegisteredForProvisionStateChangedWithSatelliteService = 271 new AtomicBoolean(false); 272 private final AtomicBoolean mRegisteredForPendingDatagramCountWithSatelliteService = 273 new AtomicBoolean(false); 274 private final AtomicBoolean mRegisteredForSatelliteModemStateChangedWithSatelliteService = 275 new AtomicBoolean(false); 276 private final AtomicBoolean mRegisteredForNtnSignalStrengthChanged = new AtomicBoolean(false); 277 private final AtomicBoolean mRegisteredForSatelliteCapabilitiesChanged = 278 new AtomicBoolean(false); 279 private final AtomicBoolean mIsModemEnabledReportingNtnSignalStrength = 280 new AtomicBoolean(false); 281 private final AtomicBoolean mLatestRequestedStateForNtnSignalStrengthReport = 282 new AtomicBoolean(false); 283 private final AtomicBoolean mRegisteredForSatelliteSupportedStateChanged = 284 new AtomicBoolean(false); 285 /** 286 * Map key: subId, value: callback to get error code of the provision request. 287 */ 288 private final ConcurrentHashMap<Integer, Consumer<Integer>> mSatelliteProvisionCallbacks = 289 new ConcurrentHashMap<>(); 290 291 /** 292 * Map key: binder of the callback, value: callback to receive provision state changed events. 293 */ 294 private final ConcurrentHashMap<IBinder, ISatelliteProvisionStateCallback> 295 mSatelliteProvisionStateChangedListeners = new ConcurrentHashMap<>(); 296 /** 297 * Map key: binder of the callback, value: callback to receive non-terrestrial signal strength 298 * state changed events. 299 */ 300 private final ConcurrentHashMap<IBinder, INtnSignalStrengthCallback> 301 mNtnSignalStrengthChangedListeners = new ConcurrentHashMap<>(); 302 /** 303 * Map key: binder of the callback, value: callback to receive satellite capabilities changed 304 * events. 305 */ 306 private final ConcurrentHashMap<IBinder, ISatelliteCapabilitiesCallback> 307 mSatelliteCapabilitiesChangedListeners = new ConcurrentHashMap<>(); 308 /** 309 * Map key: binder of the callback, value: callback to receive supported state changed events. 310 */ 311 private final ConcurrentHashMap<IBinder, ISatelliteSupportedStateCallback> 312 mSatelliteSupportedStateChangedListeners = new ConcurrentHashMap<>(); 313 private final Object mIsSatelliteSupportedLock = new Object(); 314 @GuardedBy("mIsSatelliteSupportedLock") 315 private Boolean mIsSatelliteSupported = null; 316 private boolean mIsDemoModeEnabled = false; 317 private boolean mIsEmergency = false; 318 private final Object mIsSatelliteEnabledLock = new Object(); 319 @GuardedBy("mIsSatelliteEnabledLock") 320 private Boolean mIsSatelliteEnabled = null; 321 private final Object mIsRadioOnLock = new Object(); 322 @GuardedBy("mIsRadioOnLock") 323 private boolean mIsRadioOn = false; 324 private final Object mSatelliteViaOemProvisionLock = new Object(); 325 @GuardedBy("mSatelliteViaOemProvisionLock") 326 private Boolean mIsSatelliteViaOemProvisioned = null; 327 @GuardedBy("mSatelliteViaOemProvisionLock") 328 private Boolean mOverriddenIsSatelliteViaOemProvisioned = null; 329 private final Object mSatelliteCapabilitiesLock = new Object(); 330 @GuardedBy("mSatelliteCapabilitiesLock") 331 private SatelliteCapabilities mSatelliteCapabilities; 332 private final Object mNeedsSatellitePointingLock = new Object(); 333 @GuardedBy("mNeedsSatellitePointingLock") 334 private boolean mNeedsSatellitePointing = false; 335 private final Object mNtnSignalsStrengthLock = new Object(); 336 @GuardedBy("mNtnSignalsStrengthLock") 337 private NtnSignalStrength mNtnSignalStrength = 338 new NtnSignalStrength(NTN_SIGNAL_STRENGTH_NONE); 339 /** Key: subId, value: (key: PLMN, value: set of 340 * {@link android.telephony.NetworkRegistrationInfo.ServiceType}) 341 */ 342 @GuardedBy("mSupportedSatelliteServicesLock") 343 @NonNull private final Map<Integer, Map<String, Set<Integer>>> 344 mSatelliteServicesSupportedByCarriers = new HashMap<>(); 345 @NonNull private final Object mSupportedSatelliteServicesLock = new Object(); 346 @NonNull private final List<String> mSatellitePlmnListFromOverlayConfig; 347 @NonNull private final CarrierConfigManager mCarrierConfigManager; 348 @NonNull private final CarrierConfigManager.CarrierConfigChangeListener 349 mCarrierConfigChangeListener; 350 @NonNull private final ConfigProviderAdaptor.Callback mConfigDataUpdatedCallback; 351 @NonNull private final Object mCarrierConfigArrayLock = new Object(); 352 @GuardedBy("mCarrierConfigArrayLock") 353 @NonNull private final SparseArray<PersistableBundle> mCarrierConfigArray = new SparseArray<>(); 354 @GuardedBy("mIsSatelliteEnabledLock") 355 /** Key: Subscription ID, value: set of restriction reasons for satellite communication.*/ 356 @NonNull private final Map<Integer, Set<Integer>> mSatelliteAttachRestrictionForCarrierArray = 357 new HashMap<>(); 358 @GuardedBy("mIsSatelliteEnabledLock") 359 /** Key: Subscription ID, value: the actual satellite enabled state in the modem - 360 * {@code true} for enabled and {@code false} for disabled. */ 361 @NonNull private final Map<Integer, Boolean> mIsSatelliteAttachEnabledForCarrierArrayPerSub = 362 new HashMap<>(); 363 @NonNull private final FeatureFlags mFeatureFlags; 364 @NonNull private final Object mSatelliteConnectedLock = new Object(); 365 /** Key: Subscription ID; Value: Last satellite connected time */ 366 @GuardedBy("mSatelliteConnectedLock") 367 @NonNull private final SparseArray<Long> mLastSatelliteDisconnectedTimesMillis = 368 new SparseArray<>(); 369 /** 370 * Key: Subscription ID; Value: {@code true} if satellite was just connected, 371 * {@code false} otherwise. 372 */ 373 @GuardedBy("mSatelliteConnectedLock") 374 @NonNull private final SparseBooleanArray 375 mWasSatelliteConnectedViaCarrier = new SparseBooleanArray(); 376 377 @GuardedBy("mSatelliteConnectedLock") 378 @NonNull private final SparseBooleanArray mLastNotifiedNtnMode = new SparseBooleanArray(); 379 380 @GuardedBy("mSatelliteConnectedLock") 381 @NonNull private final SparseBooleanArray mInitialized = new SparseBooleanArray(); 382 383 @GuardedBy("mSatelliteConnectedLock") 384 @NonNull private final Map<Integer, CarrierRoamingSatelliteSessionStats> 385 mCarrierRoamingSatelliteSessionStatsMap = new HashMap<>(); 386 387 /** 388 * Key: Subscription ID; Value: set of 389 * {@link android.telephony.NetworkRegistrationInfo.ServiceType} 390 */ 391 @GuardedBy("mSatelliteConnectedLock") 392 @NonNull private final Map<Integer, List<Integer>> 393 mSatModeCapabilitiesForCarrierRoaming = new HashMap<>(); 394 395 /** 396 * This is used for testing only. When mEnforcedEmergencyCallToSatelliteHandoverType is valid, 397 * Telephony will ignore the IMS registration status and cellular availability, and always send 398 * the connection event EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer. 399 */ 400 private int mEnforcedEmergencyCallToSatelliteHandoverType = 401 INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE; 402 private int mDelayInSendingEventDisplayEmergencyMessage = 0; 403 @NonNull private SharedPreferences mSharedPreferences = null; 404 405 @Nullable private PersistentLogger mPersistentLogger = null; 406 407 /** 408 * Key : Subscription ID, Value: {@code true} if the EntitlementStatus is enabled, 409 * {@code false} otherwise. 410 */ 411 @GuardedBy("mSupportedSatelliteServicesLock") 412 private SparseBooleanArray mSatelliteEntitlementStatusPerCarrier = new SparseBooleanArray(); 413 /** Key Subscription ID, value : PLMN allowed list from entitlement. */ 414 @GuardedBy("mSupportedSatelliteServicesLock") 415 private SparseArray<List<String>> mEntitlementPlmnListPerCarrier = new SparseArray<>(); 416 /** Key Subscription ID, value : PLMN barred list from entitlement. */ 417 @GuardedBy("mSupportedSatelliteServicesLock") 418 private SparseArray<List<String>> mEntitlementBarredPlmnListPerCarrier = new SparseArray<>(); 419 /** 420 * Key : Subscription ID, Value : If there is an entitlementPlmnList, use it. Otherwise, use the 421 * carrierPlmnList. */ 422 @GuardedBy("mSupportedSatelliteServicesLock") 423 private final SparseArray<List<String>> mMergedPlmnListPerCarrier = new SparseArray<>(); 424 private static AtomicLong sNextSatelliteEnableRequestId = new AtomicLong(0); 425 private long mWaitTimeForSatelliteEnablingResponse; 426 private long mDemoPointingAlignedDurationMillis; 427 private long mDemoPointingNotAlignedDurationMillis; 428 private final Object mLock = new Object(); 429 @GuardedBy("mLock") 430 private long mLastEmergencyCallTime; 431 private long mSatelliteEmergencyModeDurationMillis; 432 private static final int DEFAULT_SATELLITE_EMERGENCY_MODE_DURATION_SECONDS = 300; 433 434 /** Key used to read/write satellite system notification done in shared preferences. */ 435 private static final String SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY = 436 "satellite_system_notification_done_key"; 437 // The notification tag used when showing a notification. The combination of notification tag 438 // and notification id should be unique within the phone app. 439 private static final String NOTIFICATION_TAG = "SatelliteController"; 440 private static final int NOTIFICATION_ID = 1; 441 private static final String NOTIFICATION_CHANNEL = "satelliteChannel"; 442 private static final String NOTIFICATION_CHANNEL_ID = "satellite"; 443 444 private final RegistrantList mSatelliteConfigUpdateChangedRegistrants = new RegistrantList(); 445 private final BTWifiNFCStateReceiver mBTWifiNFCSateReceiver; 446 private final UwbAdapterStateCallback mUwbAdapterStateCallback; 447 448 private long mSessionStartTimeStamp; 449 private long mSessionProcessingTimeStamp; 450 451 // Variable for backup and restore device's screen rotation settings. 452 private String mDeviceRotationLockToBackupAndRestore = null; 453 454 /** 455 * @return The singleton instance of SatelliteController. 456 */ getInstance()457 public static SatelliteController getInstance() { 458 if (sInstance == null) { 459 loge("SatelliteController was not yet initialized."); 460 } 461 return sInstance; 462 } 463 464 /** 465 * Create the SatelliteController singleton instance. 466 * @param context The Context to use to create the SatelliteController. 467 * @param featureFlags The feature flag. 468 */ make(@onNull Context context, @NonNull FeatureFlags featureFlags)469 public static void make(@NonNull Context context, @NonNull FeatureFlags featureFlags) { 470 if (sInstance == null) { 471 HandlerThread satelliteThread = new HandlerThread(TAG); 472 satelliteThread.start(); 473 sInstance = new SatelliteController(context, satelliteThread.getLooper(), featureFlags); 474 } 475 } 476 477 /** 478 * Create a SatelliteController to act as a backend service of 479 * {@link android.telephony.satellite.SatelliteManager} 480 * 481 * @param context The Context for the SatelliteController. 482 * @param looper The looper for the handler. It does not run on main thread. 483 * @param featureFlags The feature flag. 484 */ 485 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) SatelliteController( @onNull Context context, @NonNull Looper looper, @NonNull FeatureFlags featureFlags)486 public SatelliteController( 487 @NonNull Context context, @NonNull Looper looper, @NonNull FeatureFlags featureFlags) { 488 super(looper); 489 490 if (isSatellitePersistentLoggingEnabled(context, featureFlags)) { 491 mPersistentLogger = new PersistentLogger( 492 DropBoxManagerLoggerBackend.getInstance(context)); 493 } 494 495 mContext = context; 496 mFeatureFlags = featureFlags; 497 Phone phone = SatelliteServiceUtils.getPhone(); 498 mCi = phone.mCi; 499 mDSM = phone.getDeviceStateMonitor(); 500 // Create the SatelliteModemInterface singleton, which is used to manage connections 501 // to the satellite service and HAL interface. 502 mSatelliteModemInterface = SatelliteModemInterface.make( 503 mContext, this, mFeatureFlags); 504 505 // Create the PointingUIController singleton, 506 // which is used to manage interactions with PointingUI app. 507 mPointingAppController = PointingAppController.make(mContext, mFeatureFlags); 508 509 // Create the SatelliteControllerMetrics to report controller metrics 510 // should be called before making DatagramController 511 mControllerMetricsStats = ControllerMetricsStats.make(mContext); 512 mProvisionMetricsStats = ProvisionMetricsStats.getOrCreateInstance(); 513 mSessionMetricsStats = SessionMetricsStats.getInstance(); 514 mCarrierRoamingSatelliteControllerStats = 515 CarrierRoamingSatelliteControllerStats.getOrCreateInstance(); 516 mSubscriptionManagerService = SubscriptionManagerService.getInstance(); 517 518 // Create the DatagramController singleton, 519 // which is used to send and receive satellite datagrams. 520 mDatagramController = DatagramController.make( 521 mContext, looper, mFeatureFlags, mPointingAppController); 522 523 mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null); 524 synchronized (mIsRadioOnLock) { 525 mIsRadioOn = phone.isRadioOn(); 526 } 527 528 registerForSatelliteProvisionStateChanged(); 529 registerForPendingDatagramCount(); 530 registerForSatelliteModemStateChanged(); 531 registerForServiceStateChanged(); 532 mContentResolver = mContext.getContentResolver(); 533 mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class); 534 535 mBTWifiNFCSateReceiver = new BTWifiNFCStateReceiver(); 536 mUwbAdapterStateCallback = new UwbAdapterStateCallback(); 537 initializeSatelliteModeRadios(); 538 539 ContentObserver satelliteModeRadiosContentObserver = new ContentObserver(this) { 540 @Override 541 public void onChange(boolean selfChange) { 542 initializeSatelliteModeRadios(); 543 } 544 }; 545 if (mContentResolver != null) { 546 mContentResolver.registerContentObserver( 547 Settings.Global.getUriFor(Settings.Global.SATELLITE_MODE_RADIOS), 548 false, satelliteModeRadiosContentObserver); 549 } 550 551 mSatellitePlmnListFromOverlayConfig = readSatellitePlmnsFromOverlayConfig(); 552 updateSupportedSatelliteServicesForActiveSubscriptions(); 553 mCarrierConfigChangeListener = 554 (slotIndex, subId, carrierId, specificCarrierId) -> 555 handleCarrierConfigChanged(slotIndex, subId, carrierId, specificCarrierId); 556 mCarrierConfigManager.registerCarrierConfigChangeListener( 557 new HandlerExecutor(new Handler(looper)), mCarrierConfigChangeListener); 558 559 mConfigDataUpdatedCallback = new ConfigProviderAdaptor.Callback() { 560 @Override 561 public void onChanged(@Nullable ConfigParser config) { 562 SatelliteControllerHandlerRequest request = 563 new SatelliteControllerHandlerRequest(true, 564 SatelliteServiceUtils.getPhone()); 565 sendRequestAsync(EVENT_SATELLITE_CONFIG_DATA_UPDATED, request, null); 566 } 567 }; 568 TelephonyConfigUpdateInstallReceiver.getInstance() 569 .registerCallback(Executors.newSingleThreadExecutor(), mConfigDataUpdatedCallback); 570 571 mDSM.registerForSignalStrengthReportDecision(this, CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING, 572 null); 573 loadSatelliteSharedPreferences(); 574 mWaitTimeForSatelliteEnablingResponse = getWaitForSatelliteEnablingResponseTimeoutMillis(); 575 mDemoPointingAlignedDurationMillis = getDemoPointingAlignedDurationMillisFromResources(); 576 mDemoPointingNotAlignedDurationMillis = 577 getDemoPointingNotAlignedDurationMillisFromResources(); 578 mSatelliteEmergencyModeDurationMillis = 579 getSatelliteEmergencyModeDurationFromOverlayConfig(context); 580 } 581 582 /** 583 * Register a callback to get a updated satellite config data. 584 * @param h Handler to notify 585 * @param what msg.what when the message is delivered 586 * @param obj AsyncResult.userObj when the message is delivered 587 */ registerForConfigUpdateChanged(Handler h, int what, Object obj)588 public void registerForConfigUpdateChanged(Handler h, int what, Object obj) { 589 Registrant r = new Registrant(h, what, obj); 590 mSatelliteConfigUpdateChangedRegistrants.add(r); 591 } 592 593 /** 594 * Unregister a callback to get a updated satellite config data. 595 * @param h Handler to notify 596 */ unregisterForConfigUpdateChanged(Handler h)597 public void unregisterForConfigUpdateChanged(Handler h) { 598 mSatelliteConfigUpdateChangedRegistrants.remove(h); 599 } 600 601 /** 602 * Get satelliteConfig from SatelliteConfigParser 603 */ getSatelliteConfig()604 public SatelliteConfig getSatelliteConfig() { 605 SatelliteConfigParser satelliteConfigParser = getSatelliteConfigParser(); 606 if (satelliteConfigParser == null) { 607 Log.d(TAG, "satelliteConfigParser is not ready"); 608 return null; 609 } 610 return satelliteConfigParser.getConfig(); 611 } 612 613 /** 614 * Get SatelliteConfigParser from TelephonyConfigUpdateInstallReceiver 615 */ 616 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) getSatelliteConfigParser()617 public SatelliteConfigParser getSatelliteConfigParser() { 618 return (SatelliteConfigParser) TelephonyConfigUpdateInstallReceiver 619 .getInstance().getConfigParser(DOMAIN_SATELLITE); 620 } 621 622 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) initializeSatelliteModeRadios()623 protected void initializeSatelliteModeRadios() { 624 if (mContentResolver != null) { 625 IntentFilter radioStateIntentFilter = new IntentFilter(); 626 627 synchronized (mRadioStateLock) { 628 // Initialize radio states to default value 629 mDisableBTOnSatelliteEnabled = false; 630 mDisableNFCOnSatelliteEnabled = false; 631 mDisableWifiOnSatelliteEnabled = false; 632 mDisableUWBOnSatelliteEnabled = false; 633 634 mBTStateEnabled = false; 635 mNfcStateEnabled = false; 636 mWifiStateEnabled = false; 637 mUwbStateEnabled = false; 638 639 // Read satellite mode radios from settings 640 String satelliteModeRadios = Settings.Global.getString(mContentResolver, 641 Settings.Global.SATELLITE_MODE_RADIOS); 642 if (satelliteModeRadios == null) { 643 ploge("initializeSatelliteModeRadios: satelliteModeRadios is null"); 644 return; 645 } 646 plogd("Radios To be checked when satellite is on: " + satelliteModeRadios); 647 648 if (satelliteModeRadios.contains(Settings.Global.RADIO_BLUETOOTH)) { 649 BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 650 if (bluetoothAdapter != null) { 651 mDisableBTOnSatelliteEnabled = true; 652 mBTStateEnabled = bluetoothAdapter.isEnabled(); 653 radioStateIntentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); 654 } 655 } 656 657 if (satelliteModeRadios.contains(Settings.Global.RADIO_NFC)) { 658 Context applicationContext = mContext.getApplicationContext(); 659 NfcAdapter nfcAdapter = null; 660 if (applicationContext != null) { 661 nfcAdapter = NfcAdapter.getDefaultAdapter(mContext.getApplicationContext()); 662 } 663 if (nfcAdapter != null) { 664 mDisableNFCOnSatelliteEnabled = true; 665 mNfcStateEnabled = nfcAdapter.isEnabled(); 666 radioStateIntentFilter.addAction(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 667 } 668 } 669 670 if (satelliteModeRadios.contains(Settings.Global.RADIO_WIFI)) { 671 WifiManager wifiManager = mContext.getSystemService(WifiManager.class); 672 if (wifiManager != null) { 673 mDisableWifiOnSatelliteEnabled = true; 674 mWifiStateEnabled = wifiManager.isWifiEnabled(); 675 radioStateIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 676 } 677 } 678 679 try { 680 // Unregister receiver before registering it. 681 mContext.unregisterReceiver(mBTWifiNFCSateReceiver); 682 } catch (IllegalArgumentException e) { 683 plogd("initializeSatelliteModeRadios: unregisterReceiver, e=" + e); 684 } 685 mContext.registerReceiver(mBTWifiNFCSateReceiver, radioStateIntentFilter); 686 687 if (satelliteModeRadios.contains(Settings.Global.RADIO_UWB)) { 688 UwbManager uwbManager = mContext.getSystemService(UwbManager.class); 689 if (uwbManager != null) { 690 mDisableUWBOnSatelliteEnabled = true; 691 mUwbStateEnabled = uwbManager.isUwbEnabled(); 692 final long identity = Binder.clearCallingIdentity(); 693 try { 694 // Unregister callback before registering it. 695 uwbManager.unregisterAdapterStateCallback(mUwbAdapterStateCallback); 696 uwbManager.registerAdapterStateCallback(mContext.getMainExecutor(), 697 mUwbAdapterStateCallback); 698 } finally { 699 Binder.restoreCallingIdentity(identity); 700 } 701 } 702 } 703 704 plogd("mDisableBTOnSatelliteEnabled: " + mDisableBTOnSatelliteEnabled 705 + " mDisableNFCOnSatelliteEnabled: " + mDisableNFCOnSatelliteEnabled 706 + " mDisableWifiOnSatelliteEnabled: " + mDisableWifiOnSatelliteEnabled 707 + " mDisableUWBOnSatelliteEnabled: " + mDisableUWBOnSatelliteEnabled); 708 709 plogd("mBTStateEnabled: " + mBTStateEnabled 710 + " mNfcStateEnabled: " + mNfcStateEnabled 711 + " mWifiStateEnabled: " + mWifiStateEnabled 712 + " mUwbStateEnabled: " + mUwbStateEnabled); 713 } 714 } 715 } 716 717 protected class UwbAdapterStateCallback implements UwbManager.AdapterStateCallback { 718 toString(int state)719 public String toString(int state) { 720 switch (state) { 721 case UwbManager.AdapterStateCallback.STATE_DISABLED: 722 return "Disabled"; 723 724 case UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE: 725 return "Inactive"; 726 727 case UwbManager.AdapterStateCallback.STATE_ENABLED_ACTIVE: 728 return "Active"; 729 730 default: 731 return ""; 732 } 733 } 734 735 @Override onStateChanged(int state, int reason)736 public void onStateChanged(int state, int reason) { 737 plogd("UwbAdapterStateCallback#onStateChanged() called, state = " + toString(state)); 738 plogd("Adapter state changed reason " + String.valueOf(reason)); 739 synchronized (mRadioStateLock) { 740 if (state == UwbManager.AdapterStateCallback.STATE_DISABLED) { 741 mUwbStateEnabled = false; 742 evaluateToSendSatelliteEnabledSuccess(); 743 } else { 744 mUwbStateEnabled = true; 745 } 746 plogd("mUwbStateEnabled: " + mUwbStateEnabled); 747 } 748 } 749 } 750 751 protected class BTWifiNFCStateReceiver extends BroadcastReceiver { 752 @Override onReceive(Context context, Intent intent)753 public void onReceive(Context context, Intent intent) { 754 final String action = intent.getAction(); 755 if (action == null) { 756 plogd("BTWifiNFCStateReceiver NULL action for intent " + intent); 757 return; 758 } 759 760 switch (action) { 761 case BluetoothAdapter.ACTION_STATE_CHANGED: 762 int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 763 BluetoothAdapter.ERROR); 764 synchronized (mRadioStateLock) { 765 boolean currentBTStateEnabled = mBTStateEnabled; 766 if (btState == BluetoothAdapter.STATE_OFF) { 767 mBTStateEnabled = false; 768 evaluateToSendSatelliteEnabledSuccess(); 769 } else if (btState == BluetoothAdapter.STATE_ON) { 770 mBTStateEnabled = true; 771 } 772 if (currentBTStateEnabled != mBTStateEnabled) { 773 plogd("mBTStateEnabled=" + mBTStateEnabled); 774 } 775 } 776 break; 777 778 case NfcAdapter.ACTION_ADAPTER_STATE_CHANGED: 779 int nfcState = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE, -1); 780 synchronized (mRadioStateLock) { 781 boolean currentNfcStateEnabled = mNfcStateEnabled; 782 if (nfcState == NfcAdapter.STATE_ON) { 783 mNfcStateEnabled = true; 784 } else if (nfcState == NfcAdapter.STATE_OFF) { 785 mNfcStateEnabled = false; 786 evaluateToSendSatelliteEnabledSuccess(); 787 } 788 if (currentNfcStateEnabled != mNfcStateEnabled) { 789 plogd("mNfcStateEnabled=" + mNfcStateEnabled); 790 } 791 } 792 break; 793 794 case WifiManager.WIFI_STATE_CHANGED_ACTION: 795 int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 796 WifiManager.WIFI_STATE_UNKNOWN); 797 synchronized (mRadioStateLock) { 798 boolean currentWifiStateEnabled = mWifiStateEnabled; 799 if (wifiState == WifiManager.WIFI_STATE_ENABLED) { 800 mWifiStateEnabled = true; 801 } else if (wifiState == WifiManager.WIFI_STATE_DISABLED) { 802 mWifiStateEnabled = false; 803 evaluateToSendSatelliteEnabledSuccess(); 804 } 805 if (currentWifiStateEnabled != mWifiStateEnabled) { 806 plogd("mWifiStateEnabled=" + mWifiStateEnabled); 807 } 808 } 809 break; 810 default: 811 break; 812 } 813 } 814 } 815 816 private static final class SatelliteControllerHandlerRequest { 817 /** The argument to use for the request */ 818 public @NonNull Object argument; 819 /** The caller needs to specify the phone to be used for the request */ 820 public @NonNull Phone phone; 821 /** The result of the request that is run on the main thread */ 822 public @Nullable Object result; 823 SatelliteControllerHandlerRequest(Object argument, Phone phone)824 SatelliteControllerHandlerRequest(Object argument, Phone phone) { 825 this.argument = argument; 826 this.phone = phone; 827 } 828 } 829 830 private static final class RequestSatelliteEnabledArgument { 831 public boolean enableSatellite; 832 public boolean enableDemoMode; 833 public boolean isEmergency; 834 @NonNull public Consumer<Integer> callback; 835 public long requestId; 836 RequestSatelliteEnabledArgument(boolean enableSatellite, boolean enableDemoMode, boolean isEmergency, Consumer<Integer> callback)837 RequestSatelliteEnabledArgument(boolean enableSatellite, boolean enableDemoMode, 838 boolean isEmergency, Consumer<Integer> callback) { 839 this.enableSatellite = enableSatellite; 840 this.enableDemoMode = enableDemoMode; 841 this.isEmergency = isEmergency; 842 this.callback = callback; 843 this.requestId = sNextSatelliteEnableRequestId.getAndUpdate( 844 n -> ((n + 1) % Long.MAX_VALUE)); 845 } 846 } 847 848 private static final class RequestHandleSatelliteAttachRestrictionForCarrierArgument { 849 public int subId; 850 @SatelliteManager.SatelliteCommunicationRestrictionReason 851 public int reason; 852 @NonNull public Consumer<Integer> callback; 853 RequestHandleSatelliteAttachRestrictionForCarrierArgument(int subId, @SatelliteManager.SatelliteCommunicationRestrictionReason int reason, Consumer<Integer> callback)854 RequestHandleSatelliteAttachRestrictionForCarrierArgument(int subId, 855 @SatelliteManager.SatelliteCommunicationRestrictionReason int reason, 856 Consumer<Integer> callback) { 857 this.subId = subId; 858 this.reason = reason; 859 this.callback = callback; 860 } 861 } 862 863 private static final class ProvisionSatelliteServiceArgument { 864 @NonNull public String token; 865 @NonNull public byte[] provisionData; 866 @NonNull public Consumer<Integer> callback; 867 public int subId; 868 ProvisionSatelliteServiceArgument(String token, byte[] provisionData, Consumer<Integer> callback, int subId)869 ProvisionSatelliteServiceArgument(String token, byte[] provisionData, 870 Consumer<Integer> callback, int subId) { 871 this.token = token; 872 this.provisionData = provisionData; 873 this.callback = callback; 874 this.subId = subId; 875 } 876 } 877 878 /** 879 * Arguments to send to SatelliteTransmissionUpdate registrants 880 */ 881 public static final class SatelliteTransmissionUpdateArgument { 882 @NonNull public Consumer<Integer> errorCallback; 883 @NonNull public ISatelliteTransmissionUpdateCallback callback; 884 public int subId; 885 SatelliteTransmissionUpdateArgument(Consumer<Integer> errorCallback, ISatelliteTransmissionUpdateCallback callback, int subId)886 SatelliteTransmissionUpdateArgument(Consumer<Integer> errorCallback, 887 ISatelliteTransmissionUpdateCallback callback, int subId) { 888 this.errorCallback = errorCallback; 889 this.callback = callback; 890 this.subId = subId; 891 } 892 } 893 894 @Override handleMessage(Message msg)895 public void handleMessage(Message msg) { 896 SatelliteControllerHandlerRequest request; 897 Message onCompleted; 898 AsyncResult ar; 899 900 switch(msg.what) { 901 case CMD_START_SATELLITE_TRANSMISSION_UPDATES: { 902 request = (SatelliteControllerHandlerRequest) msg.obj; 903 onCompleted = 904 obtainMessage(EVENT_START_SATELLITE_TRANSMISSION_UPDATES_DONE, request); 905 mPointingAppController.startSatelliteTransmissionUpdates(onCompleted); 906 break; 907 } 908 909 case EVENT_START_SATELLITE_TRANSMISSION_UPDATES_DONE: { 910 handleStartSatelliteTransmissionUpdatesDone((AsyncResult) msg.obj); 911 break; 912 } 913 914 case CMD_STOP_SATELLITE_TRANSMISSION_UPDATES: { 915 request = (SatelliteControllerHandlerRequest) msg.obj; 916 onCompleted = 917 obtainMessage(EVENT_STOP_SATELLITE_TRANSMISSION_UPDATES_DONE, request); 918 mPointingAppController.stopSatelliteTransmissionUpdates(onCompleted); 919 break; 920 } 921 922 case EVENT_STOP_SATELLITE_TRANSMISSION_UPDATES_DONE: { 923 ar = (AsyncResult) msg.obj; 924 request = (SatelliteControllerHandlerRequest) ar.userObj; 925 int error = SatelliteServiceUtils.getSatelliteError(ar, 926 "stopSatelliteTransmissionUpdates"); 927 ((Consumer<Integer>) request.argument).accept(error); 928 break; 929 } 930 931 case CMD_PROVISION_SATELLITE_SERVICE: { 932 request = (SatelliteControllerHandlerRequest) msg.obj; 933 ProvisionSatelliteServiceArgument argument = 934 (ProvisionSatelliteServiceArgument) request.argument; 935 if (mSatelliteProvisionCallbacks.containsKey(argument.subId)) { 936 argument.callback.accept( 937 SatelliteManager.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS); 938 notifyRequester(request); 939 break; 940 } 941 mSatelliteProvisionCallbacks.put(argument.subId, argument.callback); 942 onCompleted = obtainMessage(EVENT_PROVISION_SATELLITE_SERVICE_DONE, request); 943 // Log the current time for provision triggered 944 mProvisionMetricsStats.setProvisioningStartTime(); 945 mSatelliteModemInterface.provisionSatelliteService(argument.token, 946 argument.provisionData, onCompleted); 947 break; 948 } 949 950 case EVENT_PROVISION_SATELLITE_SERVICE_DONE: { 951 ar = (AsyncResult) msg.obj; 952 request = (SatelliteControllerHandlerRequest) ar.userObj; 953 int errorCode = SatelliteServiceUtils.getSatelliteError(ar, 954 "provisionSatelliteService"); 955 handleEventProvisionSatelliteServiceDone( 956 (ProvisionSatelliteServiceArgument) request.argument, errorCode); 957 notifyRequester(request); 958 break; 959 } 960 961 case CMD_DEPROVISION_SATELLITE_SERVICE: { 962 request = (SatelliteControllerHandlerRequest) msg.obj; 963 ProvisionSatelliteServiceArgument argument = 964 (ProvisionSatelliteServiceArgument) request.argument; 965 onCompleted = obtainMessage(EVENT_DEPROVISION_SATELLITE_SERVICE_DONE, request); 966 if (argument.callback != null) { 967 mProvisionMetricsStats.setProvisioningStartTime(); 968 } 969 mSatelliteModemInterface.deprovisionSatelliteService(argument.token, onCompleted); 970 break; 971 } 972 973 case EVENT_DEPROVISION_SATELLITE_SERVICE_DONE: { 974 ar = (AsyncResult) msg.obj; 975 request = (SatelliteControllerHandlerRequest) ar.userObj; 976 int errorCode = SatelliteServiceUtils.getSatelliteError(ar, 977 "deprovisionSatelliteService"); 978 handleEventDeprovisionSatelliteServiceDone( 979 (ProvisionSatelliteServiceArgument) request.argument, errorCode); 980 break; 981 } 982 983 case CMD_SET_SATELLITE_ENABLED: { 984 request = (SatelliteControllerHandlerRequest) msg.obj; 985 handleSatelliteEnabled(request); 986 break; 987 } 988 989 case EVENT_SET_SATELLITE_ENABLED_DONE: { 990 ar = (AsyncResult) msg.obj; 991 request = (SatelliteControllerHandlerRequest) ar.userObj; 992 RequestSatelliteEnabledArgument argument = 993 (RequestSatelliteEnabledArgument) request.argument; 994 int error = SatelliteServiceUtils.getSatelliteError(ar, "setSatelliteEnabled"); 995 plogd("EVENT_SET_SATELLITE_ENABLED_DONE = " + error); 996 997 /* 998 * The timer to wait for EVENT_SET_SATELLITE_ENABLED_DONE might have expired and 999 * thus the request resources might have been cleaned up. 1000 */ 1001 if (!shouldProcessEventSetSatelliteEnabledDone(argument)) { 1002 plogw("The request ID=" + argument.requestId + ", enableSatellite=" 1003 + argument.enableSatellite + " was already processed"); 1004 return; 1005 } 1006 stopWaitForSatelliteEnablingResponseTimer(argument); 1007 1008 if (error == SATELLITE_RESULT_SUCCESS) { 1009 if (argument.enableSatellite) { 1010 synchronized (mSatelliteEnabledRequestLock) { 1011 mWaitingForRadioDisabled = true; 1012 setDemoModeEnabled(argument.enableDemoMode); 1013 } 1014 setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_TRUE); 1015 setSettingsKeyToAllowDeviceRotation(SATELLITE_MODE_ENABLED_TRUE); 1016 evaluateToSendSatelliteEnabledSuccess(); 1017 } else { 1018 /** 1019 * Unregister Importance Listener for Pointing UI 1020 * when Satellite is disabled 1021 */ 1022 if (mNeedsSatellitePointing) { 1023 mPointingAppController.removeListenerForPointingUI(); 1024 } 1025 synchronized (mSatelliteEnabledRequestLock) { 1026 if (mSatelliteEnabledRequest != null && 1027 mSatelliteEnabledRequest.enableSatellite == true && 1028 argument.enableSatellite == false && mWaitingForRadioDisabled) { 1029 // Previous mSatelliteEnabledRequest is successful but waiting for 1030 // all radios to be turned off. 1031 mSatelliteEnabledRequest.callback.accept( 1032 SATELLITE_RESULT_SUCCESS); 1033 } 1034 } 1035 1036 synchronized (mIsSatelliteEnabledLock) { 1037 if (!mWaitingForSatelliteModemOff) { 1038 moveSatelliteToOffStateAndCleanUpResources( 1039 SATELLITE_RESULT_SUCCESS, 1040 argument.callback); 1041 } else { 1042 plogd("Wait for satellite modem off before updating satellite" 1043 + " modem state"); 1044 } 1045 mWaitingForDisableSatelliteModemResponse = false; 1046 } 1047 } 1048 // Request Ntn signal strength report when satellite enabled or disabled done. 1049 mLatestRequestedStateForNtnSignalStrengthReport.set(argument.enableSatellite); 1050 updateNtnSignalStrengthReporting(argument.enableSatellite); 1051 } else { 1052 synchronized (mSatelliteEnabledRequestLock) { 1053 if (mSatelliteEnabledRequest != null && 1054 mSatelliteEnabledRequest.enableSatellite == true && 1055 argument.enableSatellite == false && mWaitingForRadioDisabled) { 1056 // Previous mSatelliteEnabledRequest is successful but waiting for 1057 // all radios to be turned off. 1058 mSatelliteEnabledRequest.callback.accept( 1059 SATELLITE_RESULT_SUCCESS); 1060 } 1061 } 1062 notifyEnablementFailedToSatelliteSessionController(); 1063 resetSatelliteEnabledRequest(); 1064 1065 // If Satellite enable/disable request returned Error, no need to wait for radio 1066 argument.callback.accept(error); 1067 } 1068 1069 if (argument.enableSatellite) { 1070 mSessionMetricsStats.setInitializationResult(error) 1071 .setSatelliteTechnology(getSupportedNtnRadioTechnology()) 1072 .setInitializationProcessingTime( 1073 System.currentTimeMillis() - mSessionProcessingTimeStamp) 1074 .setIsDemoMode(mIsDemoModeEnabled); 1075 mSessionProcessingTimeStamp = 0; 1076 1077 if (error == SATELLITE_RESULT_SUCCESS) { 1078 mControllerMetricsStats.onSatelliteEnabled(); 1079 mControllerMetricsStats.reportServiceEnablementSuccessCount(); 1080 } else { 1081 mSessionMetricsStats.reportSessionMetrics(); 1082 mSessionStartTimeStamp = 0; 1083 mControllerMetricsStats.reportServiceEnablementFailCount(); 1084 } 1085 } else { 1086 mSessionMetricsStats.setTerminationResult(error) 1087 .setTerminationProcessingTime(System.currentTimeMillis() 1088 - mSessionProcessingTimeStamp) 1089 .setSessionDurationSec(calculateSessionDurationTimeSec()) 1090 .reportSessionMetrics(); 1091 mSessionStartTimeStamp = 0; 1092 mSessionProcessingTimeStamp = 0; 1093 1094 mControllerMetricsStats.onSatelliteDisabled(); 1095 1096 handlePersistentLoggingOnSessionEnd(mIsEmergency); 1097 1098 synchronized (mIsSatelliteEnabledLock) { 1099 mWaitingForDisableSatelliteModemResponse = false; 1100 } 1101 } 1102 break; 1103 } 1104 1105 case EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT: 1106 handleEventWaitForSatelliteEnablingResponseTimedOut( 1107 (RequestSatelliteEnabledArgument) msg.obj); 1108 break; 1109 1110 case CMD_IS_SATELLITE_ENABLED: { 1111 request = (SatelliteControllerHandlerRequest) msg.obj; 1112 onCompleted = obtainMessage(EVENT_IS_SATELLITE_ENABLED_DONE, request); 1113 mSatelliteModemInterface.requestIsSatelliteEnabled(onCompleted); 1114 break; 1115 } 1116 1117 case EVENT_IS_SATELLITE_ENABLED_DONE: { 1118 ar = (AsyncResult) msg.obj; 1119 request = (SatelliteControllerHandlerRequest) ar.userObj; 1120 int error = SatelliteServiceUtils.getSatelliteError(ar, 1121 "isSatelliteEnabled"); 1122 Bundle bundle = new Bundle(); 1123 if (error == SATELLITE_RESULT_SUCCESS) { 1124 if (ar.result == null) { 1125 ploge("isSatelliteEnabled: result is null"); 1126 error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 1127 } else { 1128 boolean enabled = ((int[]) ar.result)[0] == 1; 1129 if (DBG) plogd("isSatelliteEnabled: " + enabled); 1130 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_ENABLED, enabled); 1131 updateSatelliteEnabledState(enabled, "EVENT_IS_SATELLITE_ENABLED_DONE"); 1132 } 1133 } else if (error == SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) { 1134 updateSatelliteSupportedStateWhenSatelliteServiceConnected(false); 1135 } 1136 ((ResultReceiver) request.argument).send(error, bundle); 1137 break; 1138 } 1139 1140 case CMD_IS_SATELLITE_SUPPORTED: { 1141 request = (SatelliteControllerHandlerRequest) msg.obj; 1142 onCompleted = obtainMessage(EVENT_IS_SATELLITE_SUPPORTED_DONE, request); 1143 mSatelliteModemInterface.requestIsSatelliteSupported(onCompleted); 1144 break; 1145 } 1146 1147 case EVENT_IS_SATELLITE_SUPPORTED_DONE: { 1148 ar = (AsyncResult) msg.obj; 1149 request = (SatelliteControllerHandlerRequest) ar.userObj; 1150 int error = SatelliteServiceUtils.getSatelliteError(ar, "isSatelliteSupported"); 1151 Bundle bundle = new Bundle(); 1152 if (error == SATELLITE_RESULT_SUCCESS) { 1153 if (ar.result == null) { 1154 ploge("isSatelliteSupported: result is null"); 1155 error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 1156 } else { 1157 boolean supported = (boolean) ar.result; 1158 plogd("isSatelliteSupported: " + supported); 1159 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, supported); 1160 updateSatelliteSupportedStateWhenSatelliteServiceConnected(supported); 1161 } 1162 } 1163 ((ResultReceiver) request.argument).send(error, bundle); 1164 break; 1165 } 1166 1167 case CMD_GET_SATELLITE_CAPABILITIES: { 1168 request = (SatelliteControllerHandlerRequest) msg.obj; 1169 onCompleted = obtainMessage(EVENT_GET_SATELLITE_CAPABILITIES_DONE, request); 1170 mSatelliteModemInterface.requestSatelliteCapabilities(onCompleted); 1171 break; 1172 } 1173 1174 case EVENT_GET_SATELLITE_CAPABILITIES_DONE: { 1175 ar = (AsyncResult) msg.obj; 1176 request = (SatelliteControllerHandlerRequest) ar.userObj; 1177 int error = SatelliteServiceUtils.getSatelliteError(ar, 1178 "getSatelliteCapabilities"); 1179 Bundle bundle = new Bundle(); 1180 if (error == SATELLITE_RESULT_SUCCESS) { 1181 if (ar.result == null) { 1182 ploge("getSatelliteCapabilities: result is null"); 1183 error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 1184 } else { 1185 SatelliteCapabilities capabilities = (SatelliteCapabilities) ar.result; 1186 synchronized (mNeedsSatellitePointingLock) { 1187 mNeedsSatellitePointing = capabilities.isPointingRequired(); 1188 } 1189 if (DBG) plogd("getSatelliteCapabilities: " + capabilities); 1190 bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES, 1191 capabilities); 1192 synchronized (mSatelliteCapabilitiesLock) { 1193 mSatelliteCapabilities = capabilities; 1194 } 1195 } 1196 } 1197 ((ResultReceiver) request.argument).send(error, bundle); 1198 break; 1199 } 1200 1201 case CMD_GET_TIME_SATELLITE_NEXT_VISIBLE: { 1202 request = (SatelliteControllerHandlerRequest) msg.obj; 1203 onCompleted = obtainMessage(EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE, 1204 request); 1205 mSatelliteModemInterface.requestTimeForNextSatelliteVisibility(onCompleted); 1206 break; 1207 } 1208 1209 case EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE: { 1210 ar = (AsyncResult) msg.obj; 1211 request = (SatelliteControllerHandlerRequest) ar.userObj; 1212 int error = SatelliteServiceUtils.getSatelliteError(ar, 1213 "requestTimeForNextSatelliteVisibility"); 1214 Bundle bundle = new Bundle(); 1215 if (error == SATELLITE_RESULT_SUCCESS) { 1216 if (ar.result == null) { 1217 ploge("requestTimeForNextSatelliteVisibility: result is null"); 1218 error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 1219 } else { 1220 int nextVisibilityDuration = ((int[]) ar.result)[0]; 1221 if (DBG) { 1222 plogd("requestTimeForNextSatelliteVisibility: " 1223 + nextVisibilityDuration); 1224 } 1225 bundle.putInt(SatelliteManager.KEY_SATELLITE_NEXT_VISIBILITY, 1226 nextVisibilityDuration); 1227 } 1228 } 1229 ((ResultReceiver) request.argument).send(error, bundle); 1230 break; 1231 } 1232 1233 case EVENT_RADIO_STATE_CHANGED: { 1234 synchronized (mIsRadioOnLock) { 1235 logd("EVENT_RADIO_STATE_CHANGED: radioState=" + mCi.getRadioState()); 1236 if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON) { 1237 mIsRadioOn = true; 1238 } else if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF) { 1239 resetCarrierRoamingSatelliteModeParams(); 1240 } 1241 } 1242 1243 if (mCi.getRadioState() != TelephonyManager.RADIO_POWER_UNAVAILABLE) { 1244 if (mSatelliteModemInterface.isSatelliteServiceConnected()) { 1245 synchronized (mIsSatelliteSupportedLock) { 1246 if (mIsSatelliteSupported == null || !mIsSatelliteSupported) { 1247 ResultReceiver receiver = new ResultReceiver(this) { 1248 @Override 1249 protected void onReceiveResult( 1250 int resultCode, Bundle resultData) { 1251 plogd("onRadioStateChanged.requestIsSatelliteSupported: " 1252 + "resultCode=" + resultCode 1253 + ", resultData=" + resultData); 1254 } 1255 }; 1256 sendRequestAsync(CMD_IS_SATELLITE_SUPPORTED, receiver, null); 1257 } 1258 } 1259 } 1260 } 1261 break; 1262 } 1263 1264 case CMD_IS_SATELLITE_PROVISIONED: { 1265 request = (SatelliteControllerHandlerRequest) msg.obj; 1266 onCompleted = obtainMessage(EVENT_IS_SATELLITE_PROVISIONED_DONE, request); 1267 mSatelliteModemInterface.requestIsSatelliteProvisioned(onCompleted); 1268 break; 1269 } 1270 1271 case EVENT_IS_SATELLITE_PROVISIONED_DONE: { 1272 handleIsSatelliteProvisionedDoneEvent((AsyncResult) msg.obj); 1273 break; 1274 } 1275 1276 case EVENT_SATELLITE_PROVISION_STATE_CHANGED: 1277 ar = (AsyncResult) msg.obj; 1278 if (ar.result == null) { 1279 ploge("EVENT_SATELLITE_PROVISION_STATE_CHANGED: result is null"); 1280 } else { 1281 handleEventSatelliteProvisionStateChanged((boolean) ar.result); 1282 } 1283 break; 1284 1285 case EVENT_PENDING_DATAGRAMS: 1286 plogd("Received EVENT_PENDING_DATAGRAMS"); 1287 IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() { 1288 @Override 1289 public void accept(int result) { 1290 plogd("pollPendingSatelliteDatagram result: " + result); 1291 } 1292 }; 1293 pollPendingDatagrams( 1294 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, internalCallback); 1295 break; 1296 1297 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 1298 ar = (AsyncResult) msg.obj; 1299 if (ar.result == null) { 1300 ploge("EVENT_SATELLITE_MODEM_STATE_CHANGED: result is null"); 1301 } else { 1302 handleEventSatelliteModemStateChanged((int) ar.result); 1303 } 1304 break; 1305 1306 case EVENT_SET_SATELLITE_PLMN_INFO_DONE: 1307 handleSetSatellitePlmnInfoDoneEvent(msg); 1308 break; 1309 1310 case CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE: { 1311 plogd("CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE"); 1312 request = (SatelliteControllerHandlerRequest) msg.obj; 1313 handleRequestSatelliteAttachRestrictionForCarrierCmd(request); 1314 break; 1315 } 1316 1317 case EVENT_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE_DONE: { 1318 ar = (AsyncResult) msg.obj; 1319 request = (SatelliteControllerHandlerRequest) ar.userObj; 1320 RequestHandleSatelliteAttachRestrictionForCarrierArgument argument = 1321 (RequestHandleSatelliteAttachRestrictionForCarrierArgument) 1322 request.argument; 1323 int subId = argument.subId; 1324 int error = SatelliteServiceUtils.getSatelliteError(ar, 1325 "requestSetSatelliteEnabledForCarrier"); 1326 1327 synchronized (mIsSatelliteEnabledLock) { 1328 if (error == SATELLITE_RESULT_SUCCESS) { 1329 boolean enableSatellite = mSatelliteAttachRestrictionForCarrierArray 1330 .getOrDefault(argument.subId, Collections.emptySet()).isEmpty(); 1331 mIsSatelliteAttachEnabledForCarrierArrayPerSub.put(subId, enableSatellite); 1332 } else { 1333 mIsSatelliteAttachEnabledForCarrierArrayPerSub.remove(subId); 1334 } 1335 } 1336 1337 argument.callback.accept(error); 1338 break; 1339 } 1340 1341 case CMD_REQUEST_NTN_SIGNAL_STRENGTH: { 1342 plogd("CMD_REQUEST_NTN_SIGNAL_STRENGTH"); 1343 request = (SatelliteControllerHandlerRequest) msg.obj; 1344 onCompleted = obtainMessage(EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE, request); 1345 mSatelliteModemInterface.requestNtnSignalStrength(onCompleted); 1346 break; 1347 } 1348 1349 case EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE: { 1350 ar = (AsyncResult) msg.obj; 1351 request = (SatelliteControllerHandlerRequest) ar.userObj; 1352 ResultReceiver result = (ResultReceiver) request.argument; 1353 int errorCode = SatelliteServiceUtils.getSatelliteError(ar, 1354 "requestNtnSignalStrength"); 1355 if (errorCode == SATELLITE_RESULT_SUCCESS) { 1356 NtnSignalStrength ntnSignalStrength = (NtnSignalStrength) ar.result; 1357 if (ntnSignalStrength != null) { 1358 synchronized (mNtnSignalsStrengthLock) { 1359 mNtnSignalStrength = ntnSignalStrength; 1360 } 1361 Bundle bundle = new Bundle(); 1362 bundle.putParcelable(KEY_NTN_SIGNAL_STRENGTH, ntnSignalStrength); 1363 result.send(SATELLITE_RESULT_SUCCESS, bundle); 1364 } else { 1365 synchronized (mNtnSignalsStrengthLock) { 1366 if (mNtnSignalStrength.getLevel() != NTN_SIGNAL_STRENGTH_NONE) { 1367 mNtnSignalStrength = new NtnSignalStrength( 1368 NTN_SIGNAL_STRENGTH_NONE); 1369 } 1370 } 1371 ploge("EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE: ntnSignalStrength is null"); 1372 result.send(SatelliteManager.SATELLITE_RESULT_REQUEST_FAILED, null); 1373 } 1374 } else { 1375 synchronized (mNtnSignalsStrengthLock) { 1376 if (mNtnSignalStrength.getLevel() != NTN_SIGNAL_STRENGTH_NONE) { 1377 mNtnSignalStrength = new NtnSignalStrength(NTN_SIGNAL_STRENGTH_NONE); 1378 } 1379 } 1380 result.send(errorCode, null); 1381 } 1382 break; 1383 } 1384 1385 case EVENT_NTN_SIGNAL_STRENGTH_CHANGED: { 1386 ar = (AsyncResult) msg.obj; 1387 if (ar.result == null) { 1388 ploge("EVENT_NTN_SIGNAL_STRENGTH_CHANGED: result is null"); 1389 } else { 1390 handleEventNtnSignalStrengthChanged((NtnSignalStrength) ar.result); 1391 } 1392 break; 1393 } 1394 1395 case CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING: { 1396 ar = (AsyncResult) msg.obj; 1397 boolean shouldReport = (boolean) ar.result; 1398 if (DBG) { 1399 plogd("CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING: shouldReport=" + shouldReport); 1400 } 1401 handleCmdUpdateNtnSignalStrengthReporting(shouldReport); 1402 break; 1403 } 1404 1405 case EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE: { 1406 ar = (AsyncResult) msg.obj; 1407 request = (SatelliteControllerHandlerRequest) ar.userObj; 1408 boolean shouldReport = (boolean) request.argument; 1409 int errorCode = SatelliteServiceUtils.getSatelliteError(ar, 1410 "EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE: shouldReport=" 1411 + shouldReport); 1412 if (errorCode == SATELLITE_RESULT_SUCCESS) { 1413 mIsModemEnabledReportingNtnSignalStrength.set(shouldReport); 1414 if (mLatestRequestedStateForNtnSignalStrengthReport.get() 1415 != mIsModemEnabledReportingNtnSignalStrength.get()) { 1416 logd("mLatestRequestedStateForNtnSignalStrengthReport does not match with " 1417 + "mIsModemEnabledReportingNtnSignalStrength"); 1418 updateNtnSignalStrengthReporting( 1419 mLatestRequestedStateForNtnSignalStrengthReport.get()); 1420 } 1421 } else { 1422 loge(((boolean) request.argument ? "startSendingNtnSignalStrength" 1423 : "stopSendingNtnSignalStrength") + "returns " + errorCode); 1424 } 1425 break; 1426 } 1427 1428 case EVENT_SERVICE_STATE_CHANGED: { 1429 handleEventServiceStateChanged(); 1430 break; 1431 } 1432 1433 case EVENT_SATELLITE_CAPABILITIES_CHANGED: { 1434 ar = (AsyncResult) msg.obj; 1435 if (ar.result == null) { 1436 ploge("EVENT_SATELLITE_CAPABILITIES_CHANGED: result is null"); 1437 } else { 1438 handleEventSatelliteCapabilitiesChanged((SatelliteCapabilities) ar.result); 1439 } 1440 break; 1441 } 1442 1443 case EVENT_SATELLITE_SUPPORTED_STATE_CHANGED: { 1444 ar = (AsyncResult) msg.obj; 1445 if (ar.result == null) { 1446 ploge("EVENT_SATELLITE_SUPPORTED_STATE_CHANGED: result is null"); 1447 } else { 1448 handleEventSatelliteSupportedStateChanged((boolean) ar.result); 1449 } 1450 break; 1451 } 1452 1453 case EVENT_SATELLITE_CONFIG_DATA_UPDATED: { 1454 handleEventConfigDataUpdated(); 1455 mSatelliteConfigUpdateChangedRegistrants.notifyRegistrants(); 1456 break; 1457 } 1458 1459 case EVENT_NOTIFY_NTN_HYSTERESIS_TIMED_OUT: { 1460 int phoneId = (int) msg.obj; 1461 Phone phone = PhoneFactory.getPhone(phoneId); 1462 updateLastNotifiedNtnModeAndNotify(phone); 1463 break; 1464 } 1465 1466 default: 1467 Log.w(TAG, "SatelliteControllerHandler: unexpected message code: " + 1468 msg.what); 1469 break; 1470 } 1471 } 1472 handleEventConfigDataUpdated()1473 private void handleEventConfigDataUpdated() { 1474 updateSupportedSatelliteServicesForActiveSubscriptions(); 1475 int[] activeSubIds = mSubscriptionManagerService.getActiveSubIdList(true); 1476 if (activeSubIds != null) { 1477 for (int subId : activeSubIds) { 1478 processNewCarrierConfigData(subId); 1479 } 1480 } else { 1481 ploge("updateSupportedSatelliteServicesForActiveSubscriptions: " 1482 + "activeSubIds is null"); 1483 } 1484 } 1485 notifyRequester(SatelliteControllerHandlerRequest request)1486 private void notifyRequester(SatelliteControllerHandlerRequest request) { 1487 synchronized (request) { 1488 request.notifyAll(); 1489 } 1490 } 1491 1492 /** 1493 * Request to enable or disable the satellite modem and demo mode. If the satellite modem is 1494 * enabled, this will also disable the cellular modem, and if the satellite modem is disabled, 1495 * this will also re-enable the cellular modem. 1496 * 1497 * @param subId The subId of the subscription to set satellite enabled for. 1498 * @param enableSatellite {@code true} to enable the satellite modem and 1499 * {@code false} to disable. 1500 * @param enableDemoMode {@code true} to enable demo mode and {@code false} to disable. 1501 * @param isEmergency {@code true} to enable emergency mode, {@code false} otherwise. 1502 * @param callback The callback to get the error code of the request. 1503 */ requestSatelliteEnabled(int subId, boolean enableSatellite, boolean enableDemoMode, boolean isEmergency, @NonNull IIntegerConsumer callback)1504 public void requestSatelliteEnabled(int subId, boolean enableSatellite, boolean enableDemoMode, 1505 boolean isEmergency, @NonNull IIntegerConsumer callback) { 1506 plogd("requestSatelliteEnabled subId: " + subId + " enableSatellite: " + enableSatellite 1507 + " enableDemoMode: " + enableDemoMode + " isEmergency: " + isEmergency); 1508 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 1509 int error = evaluateOemSatelliteRequestAllowed(true); 1510 if (error != SATELLITE_RESULT_SUCCESS) { 1511 sendErrorAndReportSessionMetrics(error, result); 1512 return; 1513 } 1514 1515 if (enableSatellite) { 1516 synchronized (mIsRadioOnLock) { 1517 if (!mIsRadioOn) { 1518 ploge("Radio is not on, can not enable satellite"); 1519 sendErrorAndReportSessionMetrics( 1520 SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE, result); 1521 return; 1522 } 1523 } 1524 } else { 1525 /* if disable satellite, always assume demo is also disabled */ 1526 enableDemoMode = false; 1527 } 1528 1529 synchronized (mIsSatelliteEnabledLock) { 1530 if (mIsSatelliteEnabled != null) { 1531 if (mIsSatelliteEnabled == enableSatellite) { 1532 if (enableDemoMode != mIsDemoModeEnabled) { 1533 ploge("Received invalid demo mode while satellite session is enabled" 1534 + " enableDemoMode = " + enableDemoMode); 1535 sendErrorAndReportSessionMetrics( 1536 SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS, result); 1537 return; 1538 } else { 1539 plogd("Enable request matches with current state" 1540 + " enableSatellite = " + enableSatellite); 1541 sendErrorAndReportSessionMetrics( 1542 SatelliteManager.SATELLITE_RESULT_SUCCESS, result); 1543 return; 1544 } 1545 } 1546 } 1547 } 1548 1549 RequestSatelliteEnabledArgument request = 1550 new RequestSatelliteEnabledArgument(enableSatellite, enableDemoMode, isEmergency, 1551 result); 1552 /** 1553 * Multiple satellite enabled requests are handled as below: 1554 * 1. If there are no ongoing requests, store current request in mSatelliteEnabledRequest 1555 * 2. If there is a ongoing request, then: 1556 * 1. ongoing request = enable, current request = enable: return IN_PROGRESS error 1557 * 2. ongoing request = disable, current request = disable: return IN_PROGRESS error 1558 * 3. ongoing request = disable, current request = enable: return 1559 * SATELLITE_RESULT_ERROR error 1560 * 4. ongoing request = enable, current request = disable: send request to modem 1561 */ 1562 synchronized (mSatelliteEnabledRequestLock) { 1563 if (mSatelliteEnabledRequest == null) { 1564 mSatelliteEnabledRequest = request; 1565 } else if (mSatelliteEnabledRequest.enableSatellite == request.enableSatellite) { 1566 plogd("requestSatelliteEnabled enableSatellite: " + enableSatellite 1567 + " is already in progress."); 1568 sendErrorAndReportSessionMetrics( 1569 SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS, result); 1570 return; 1571 } else if (mSatelliteEnabledRequest.enableSatellite == false 1572 && request.enableSatellite == true) { 1573 plogd("requestSatelliteEnabled enableSatellite: " + enableSatellite + " cannot be " 1574 + "processed. Disable satellite is already in progress."); 1575 sendErrorAndReportSessionMetrics( 1576 SatelliteManager.SATELLITE_RESULT_ERROR, result); 1577 return; 1578 } 1579 } 1580 1581 sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null); 1582 } 1583 1584 /** 1585 * Request to get whether the satellite modem is enabled. 1586 * 1587 * @param subId The subId of the subscription to check whether satellite is enabled for. 1588 * @param result The result receiver that returns whether the satellite modem is enabled 1589 * if the request is successful or an error code if the request failed. 1590 */ requestIsSatelliteEnabled(int subId, @NonNull ResultReceiver result)1591 public void requestIsSatelliteEnabled(int subId, @NonNull ResultReceiver result) { 1592 int error = evaluateOemSatelliteRequestAllowed(false); 1593 if (error != SATELLITE_RESULT_SUCCESS) { 1594 result.send(error, null); 1595 return; 1596 } 1597 1598 synchronized (mIsSatelliteEnabledLock) { 1599 if (mIsSatelliteEnabled != null) { 1600 /* We have already successfully queried the satellite modem. */ 1601 Bundle bundle = new Bundle(); 1602 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_ENABLED, mIsSatelliteEnabled); 1603 result.send(SATELLITE_RESULT_SUCCESS, bundle); 1604 return; 1605 } 1606 } 1607 1608 sendRequestAsync(CMD_IS_SATELLITE_ENABLED, result, null); 1609 } 1610 1611 /** 1612 * Get whether the satellite modem is enabled. 1613 * This will return the cached value instead of querying the satellite modem. 1614 * 1615 * @return {@code true} if the satellite modem is enabled and {@code false} otherwise. 1616 */ isSatelliteEnabled()1617 public boolean isSatelliteEnabled() { 1618 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 1619 plogd("isSatelliteEnabled: oemEnabledSatelliteFlag is disabled"); 1620 return false; 1621 } 1622 if (mIsSatelliteEnabled == null) return false; 1623 return mIsSatelliteEnabled; 1624 } 1625 1626 /** 1627 * Get whether satellite modem is being enabled. 1628 * 1629 * @return {@code true} if the satellite modem is being enabled and {@code false} otherwise. 1630 */ isSatelliteBeingEnabled()1631 public boolean isSatelliteBeingEnabled() { 1632 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 1633 plogd("isSatelliteBeingEnabled: oemEnabledSatelliteFlag is disabled"); 1634 return false; 1635 } 1636 1637 if (mSatelliteSessionController != null) { 1638 return mSatelliteSessionController.isInEnablingState(); 1639 } 1640 return false; 1641 } 1642 1643 /** 1644 * Request to get whether the satellite service demo mode is enabled. 1645 * 1646 * @param subId The subId of the subscription to check whether the satellite demo mode 1647 * is enabled for. 1648 * @param result The result receiver that returns whether the satellite demo mode is enabled 1649 * if the request is successful or an error code if the request failed. 1650 */ requestIsDemoModeEnabled(int subId, @NonNull ResultReceiver result)1651 public void requestIsDemoModeEnabled(int subId, @NonNull ResultReceiver result) { 1652 int error = evaluateOemSatelliteRequestAllowed(true); 1653 if (error != SATELLITE_RESULT_SUCCESS) { 1654 result.send(error, null); 1655 return; 1656 } 1657 1658 final Bundle bundle = new Bundle(); 1659 bundle.putBoolean(SatelliteManager.KEY_DEMO_MODE_ENABLED, mIsDemoModeEnabled); 1660 result.send(SATELLITE_RESULT_SUCCESS, bundle); 1661 } 1662 1663 /** 1664 * Get whether the satellite service demo mode is enabled. 1665 * 1666 * @return {@code true} if the satellite demo mode is enabled and {@code false} otherwise. 1667 */ isDemoModeEnabled()1668 public boolean isDemoModeEnabled() { 1669 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 1670 plogd("isDemoModeEnabled: oemEnabledSatelliteFlag is disabled"); 1671 return false; 1672 } 1673 return mIsDemoModeEnabled; 1674 } 1675 1676 /** 1677 * Request to get whether the satellite service is supported on the device. 1678 * 1679 * @param subId The subId of the subscription to check satellite service support for. 1680 * @param result The result receiver that returns whether the satellite service is supported on 1681 * the device if the request is successful or an error code if the request failed. 1682 */ requestIsSatelliteSupported(int subId, @NonNull ResultReceiver result)1683 public void requestIsSatelliteSupported(int subId, @NonNull ResultReceiver result) { 1684 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 1685 plogd("requestIsSatelliteSupported: oemEnabledSatelliteFlag is disabled"); 1686 result.send(SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED, null); 1687 return; 1688 } 1689 synchronized (mIsSatelliteSupportedLock) { 1690 if (mIsSatelliteSupported != null) { 1691 /* We have already successfully queried the satellite modem. */ 1692 Bundle bundle = new Bundle(); 1693 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, mIsSatelliteSupported); 1694 bundle.putInt(SATELLITE_SUBSCRIPTION_ID, subId); 1695 result.send(SATELLITE_RESULT_SUCCESS, bundle); 1696 return; 1697 } 1698 } 1699 1700 sendRequestAsync(CMD_IS_SATELLITE_SUPPORTED, result, null); 1701 } 1702 1703 /** 1704 * Request to get the {@link SatelliteCapabilities} of the satellite service. 1705 * 1706 * @param subId The subId of the subscription to get the satellite capabilities for. 1707 * @param result The result receiver that returns the {@link SatelliteCapabilities} 1708 * if the request is successful or an error code if the request failed. 1709 */ requestSatelliteCapabilities(int subId, @NonNull ResultReceiver result)1710 public void requestSatelliteCapabilities(int subId, @NonNull ResultReceiver result) { 1711 int error = evaluateOemSatelliteRequestAllowed(false); 1712 if (error != SATELLITE_RESULT_SUCCESS) { 1713 result.send(error, null); 1714 return; 1715 } 1716 1717 synchronized (mSatelliteCapabilitiesLock) { 1718 if (mSatelliteCapabilities != null) { 1719 Bundle bundle = new Bundle(); 1720 bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES, 1721 mSatelliteCapabilities); 1722 result.send(SATELLITE_RESULT_SUCCESS, bundle); 1723 return; 1724 } 1725 } 1726 1727 sendRequestAsync(CMD_GET_SATELLITE_CAPABILITIES, result, null); 1728 } 1729 1730 /** 1731 * Start receiving satellite transmission updates. 1732 * This can be called by the pointing UI when the user starts pointing to the satellite. 1733 * Modem should continue to report the pointing input as the device or satellite moves. 1734 * 1735 * @param subId The subId of the subscription to start satellite transmission updates for. 1736 * @param errorCallback The callback to get the error code of the request. 1737 * @param callback The callback to notify of satellite transmission updates. 1738 */ startSatelliteTransmissionUpdates(int subId, @NonNull IIntegerConsumer errorCallback, @NonNull ISatelliteTransmissionUpdateCallback callback)1739 public void startSatelliteTransmissionUpdates(int subId, 1740 @NonNull IIntegerConsumer errorCallback, 1741 @NonNull ISatelliteTransmissionUpdateCallback callback) { 1742 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(errorCallback::accept); 1743 int error = evaluateOemSatelliteRequestAllowed(true); 1744 if (error != SATELLITE_RESULT_SUCCESS) { 1745 result.accept(error); 1746 return; 1747 } 1748 1749 final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext); 1750 mPointingAppController.registerForSatelliteTransmissionUpdates(validSubId, callback); 1751 sendRequestAsync(CMD_START_SATELLITE_TRANSMISSION_UPDATES, 1752 new SatelliteTransmissionUpdateArgument(result, callback, validSubId), null); 1753 } 1754 1755 /** 1756 * Stop receiving satellite transmission updates. 1757 * This can be called by the pointing UI when the user stops pointing to the satellite. 1758 * 1759 * @param subId The subId of the subscription to stop satellite transmission updates for. 1760 * @param errorCallback The callback to get the error code of the request. 1761 * @param callback The callback that was passed to {@link #startSatelliteTransmissionUpdates( 1762 * int, IIntegerConsumer, ISatelliteTransmissionUpdateCallback)}. 1763 */ stopSatelliteTransmissionUpdates(int subId, @NonNull IIntegerConsumer errorCallback, @NonNull ISatelliteTransmissionUpdateCallback callback)1764 public void stopSatelliteTransmissionUpdates(int subId, @NonNull IIntegerConsumer errorCallback, 1765 @NonNull ISatelliteTransmissionUpdateCallback callback) { 1766 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(errorCallback::accept); 1767 int error = evaluateOemSatelliteRequestAllowed(true); 1768 if (error != SATELLITE_RESULT_SUCCESS) { 1769 result.accept(error); 1770 return; 1771 } 1772 1773 final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext); 1774 mPointingAppController.unregisterForSatelliteTransmissionUpdates( 1775 validSubId, result, callback); 1776 1777 // Even if handler is null - which means there are no listeners, the modem command to stop 1778 // satellite transmission updates might have failed. The callers might want to retry 1779 // sending the command. Thus, we always need to send this command to the modem. 1780 sendRequestAsync(CMD_STOP_SATELLITE_TRANSMISSION_UPDATES, result, null); 1781 } 1782 1783 /** 1784 * Register the subscription with a satellite provider. 1785 * This is needed to register the subscription if the provider allows dynamic registration. 1786 * 1787 * @param subId The subId of the subscription to be provisioned. 1788 * @param token The token to be used as a unique identifier for provisioning with satellite 1789 * gateway. 1790 * @param provisionData Data from the provisioning app that can be used by provisioning server 1791 * @param callback The callback to get the error code of the request. 1792 * 1793 * @return The signal transport used by the caller to cancel the provision request, 1794 * or {@code null} if the request failed. 1795 */ provisionSatelliteService(int subId, @NonNull String token, @NonNull byte[] provisionData, @NonNull IIntegerConsumer callback)1796 @Nullable public ICancellationSignal provisionSatelliteService(int subId, 1797 @NonNull String token, @NonNull byte[] provisionData, 1798 @NonNull IIntegerConsumer callback) { 1799 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 1800 int error = evaluateOemSatelliteRequestAllowed(false); 1801 if (error != SATELLITE_RESULT_SUCCESS) { 1802 result.accept(error); 1803 return null; 1804 } 1805 1806 final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext); 1807 if (mSatelliteProvisionCallbacks.containsKey(validSubId)) { 1808 result.accept(SatelliteManager.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS); 1809 return null; 1810 } 1811 1812 Boolean satelliteProvisioned = isSatelliteViaOemProvisioned(); 1813 if (satelliteProvisioned != null && satelliteProvisioned) { 1814 result.accept(SATELLITE_RESULT_SUCCESS); 1815 return null; 1816 } 1817 1818 sendRequestAsync(CMD_PROVISION_SATELLITE_SERVICE, 1819 new ProvisionSatelliteServiceArgument(token, provisionData, result, validSubId), 1820 null); 1821 1822 ICancellationSignal cancelTransport = CancellationSignal.createTransport(); 1823 CancellationSignal.fromTransport(cancelTransport).setOnCancelListener(() -> { 1824 sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE, 1825 new ProvisionSatelliteServiceArgument(token, provisionData, null, 1826 validSubId), null); 1827 mProvisionMetricsStats.setIsCanceled(true); 1828 }); 1829 return cancelTransport; 1830 } 1831 1832 /** 1833 * Unregister the device/subscription with the satellite provider. 1834 * This is needed if the provider allows dynamic registration. Once deprovisioned, 1835 * {@link android.telephony.satellite.SatelliteProvisionStateCallback 1836 * #onSatelliteProvisionStateChanged(boolean)} 1837 * should report as deprovisioned. 1838 * 1839 * @param subId The subId of the subscription to be deprovisioned. 1840 * @param token The token of the device/subscription to be deprovisioned. 1841 * @param callback The callback to get the error code of the request. 1842 */ deprovisionSatelliteService(int subId, @NonNull String token, @NonNull IIntegerConsumer callback)1843 public void deprovisionSatelliteService(int subId, 1844 @NonNull String token, @NonNull IIntegerConsumer callback) { 1845 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 1846 int error = evaluateOemSatelliteRequestAllowed(false); 1847 if (error != SATELLITE_RESULT_SUCCESS) { 1848 result.accept(error); 1849 return; 1850 } 1851 1852 Boolean satelliteProvisioned = isSatelliteViaOemProvisioned(); 1853 if (satelliteProvisioned == null) { 1854 result.accept(SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE); 1855 return; 1856 } 1857 if (!satelliteProvisioned) { 1858 result.accept(SATELLITE_RESULT_SUCCESS); 1859 return; 1860 } 1861 1862 final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext); 1863 sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE, 1864 new ProvisionSatelliteServiceArgument(token, null, result, validSubId), 1865 null); 1866 } 1867 1868 /** 1869 * Registers for the satellite provision state changed. 1870 * 1871 * @param subId The subId of the subscription to register for provision state changed. 1872 * @param callback The callback to handle the satellite provision state changed event. 1873 * 1874 * @return The {@link SatelliteManager.SatelliteResult} result of the operation. 1875 */ registerForSatelliteProvisionStateChanged( int subId, @NonNull ISatelliteProvisionStateCallback callback)1876 @SatelliteManager.SatelliteResult public int registerForSatelliteProvisionStateChanged( 1877 int subId, @NonNull ISatelliteProvisionStateCallback callback) { 1878 int error = evaluateOemSatelliteRequestAllowed(false); 1879 if (error != SATELLITE_RESULT_SUCCESS) { 1880 return error; 1881 } 1882 1883 mSatelliteProvisionStateChangedListeners.put(callback.asBinder(), callback); 1884 return SATELLITE_RESULT_SUCCESS; 1885 } 1886 1887 /** 1888 * Unregisters for the satellite provision state changed. 1889 * If callback was not registered before, the request will be ignored. 1890 * 1891 * @param subId The subId of the subscription to unregister for provision state changed. 1892 * @param callback The callback that was passed to 1893 * {@link #registerForSatelliteProvisionStateChanged(int, ISatelliteProvisionStateCallback)}. 1894 */ unregisterForSatelliteProvisionStateChanged( int subId, @NonNull ISatelliteProvisionStateCallback callback)1895 public void unregisterForSatelliteProvisionStateChanged( 1896 int subId, @NonNull ISatelliteProvisionStateCallback callback) { 1897 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 1898 plogd("unregisterForSatelliteProvisionStateChanged: " 1899 + "oemEnabledSatelliteFlag is disabled"); 1900 return; 1901 } 1902 mSatelliteProvisionStateChangedListeners.remove(callback.asBinder()); 1903 } 1904 1905 /** 1906 * Request to get whether the device is provisioned with a satellite provider. 1907 * 1908 * @param subId The subId of the subscription to get whether the device is provisioned for. 1909 * @param result The result receiver that returns whether the device is provisioned with a 1910 * satellite provider if the request is successful or an error code if the 1911 * request failed. 1912 */ requestIsSatelliteProvisioned(int subId, @NonNull ResultReceiver result)1913 public void requestIsSatelliteProvisioned(int subId, @NonNull ResultReceiver result) { 1914 int error = evaluateOemSatelliteRequestAllowed(false); 1915 if (error != SATELLITE_RESULT_SUCCESS) { 1916 result.send(error, null); 1917 return; 1918 } 1919 1920 synchronized (mSatelliteViaOemProvisionLock) { 1921 if (mIsSatelliteViaOemProvisioned != null) { 1922 Bundle bundle = new Bundle(); 1923 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED, 1924 mIsSatelliteViaOemProvisioned); 1925 result.send(SATELLITE_RESULT_SUCCESS, bundle); 1926 return; 1927 } 1928 } 1929 1930 sendRequestAsync(CMD_IS_SATELLITE_PROVISIONED, result, null); 1931 } 1932 1933 /** 1934 * Registers for modem state changed from satellite modem. 1935 * 1936 * @param subId The subId of the subscription to register for satellite modem state changed. 1937 * @param callback The callback to handle the satellite modem state changed event. 1938 * 1939 * @return The {@link SatelliteManager.SatelliteResult} result of the operation. 1940 */ registerForSatelliteModemStateChanged(int subId, @NonNull ISatelliteModemStateCallback callback)1941 @SatelliteManager.SatelliteResult public int registerForSatelliteModemStateChanged(int subId, 1942 @NonNull ISatelliteModemStateCallback callback) { 1943 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 1944 plogd("registerForSatelliteModemStateChanged: oemEnabledSatelliteFlag is disabled"); 1945 return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED; 1946 } 1947 if (mSatelliteSessionController != null) { 1948 mSatelliteSessionController.registerForSatelliteModemStateChanged(callback); 1949 } else { 1950 ploge("registerForSatelliteModemStateChanged: mSatelliteSessionController" 1951 + " is not initialized yet"); 1952 return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 1953 } 1954 return SATELLITE_RESULT_SUCCESS; 1955 } 1956 1957 /** 1958 * Unregisters for modem state changed from satellite modem. 1959 * If callback was not registered before, the request will be ignored. 1960 * 1961 * @param subId The subId of the subscription to unregister for satellite modem state changed. 1962 * @param callback The callback that was passed to 1963 * {@link #registerForSatelliteModemStateChanged(int, ISatelliteModemStateCallback)}. 1964 */ unregisterForModemStateChanged(int subId, @NonNull ISatelliteModemStateCallback callback)1965 public void unregisterForModemStateChanged(int subId, 1966 @NonNull ISatelliteModemStateCallback callback) { 1967 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 1968 plogd("unregisterForModemStateChanged: oemEnabledSatelliteFlag is disabled"); 1969 return; 1970 } 1971 if (mSatelliteSessionController != null) { 1972 mSatelliteSessionController.unregisterForSatelliteModemStateChanged(callback); 1973 } else { 1974 ploge("unregisterForModemStateChanged: mSatelliteSessionController" 1975 + " is not initialized yet"); 1976 } 1977 } 1978 1979 /** 1980 * Register to receive incoming datagrams over satellite. 1981 * 1982 * @param subId The subId of the subscription to register for incoming satellite datagrams. 1983 * @param callback The callback to handle incoming datagrams over satellite. 1984 * 1985 * @return The {@link SatelliteManager.SatelliteResult} result of the operation. 1986 */ registerForIncomingDatagram(int subId, @NonNull ISatelliteDatagramCallback callback)1987 @SatelliteManager.SatelliteResult public int registerForIncomingDatagram(int subId, 1988 @NonNull ISatelliteDatagramCallback callback) { 1989 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 1990 plogd("registerForIncomingDatagram: oemEnabledSatelliteFlag is disabled"); 1991 return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED; 1992 } 1993 if (!mSatelliteModemInterface.isSatelliteServiceSupported()) { 1994 return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED; 1995 } 1996 plogd("registerForIncomingDatagram: callback=" + callback); 1997 return mDatagramController.registerForSatelliteDatagram(subId, callback); 1998 } 1999 2000 /** 2001 * Unregister to stop receiving incoming datagrams over satellite. 2002 * If callback was not registered before, the request will be ignored. 2003 * 2004 * @param subId The subId of the subscription to unregister for incoming satellite datagrams. 2005 * @param callback The callback that was passed to 2006 * {@link #registerForIncomingDatagram(int, ISatelliteDatagramCallback)}. 2007 */ unregisterForIncomingDatagram(int subId, @NonNull ISatelliteDatagramCallback callback)2008 public void unregisterForIncomingDatagram(int subId, 2009 @NonNull ISatelliteDatagramCallback callback) { 2010 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2011 plogd("unregisterForIncomingDatagram: oemEnabledSatelliteFlag is disabled"); 2012 return; 2013 } 2014 if (!mSatelliteModemInterface.isSatelliteServiceSupported()) { 2015 return; 2016 } 2017 plogd("unregisterForIncomingDatagram: callback=" + callback); 2018 mDatagramController.unregisterForSatelliteDatagram(subId, callback); 2019 } 2020 2021 /** 2022 * Poll pending satellite datagrams over satellite. 2023 * 2024 * This method requests modem to check if there are any pending datagrams to be received over 2025 * satellite. If there are any incoming datagrams, they will be received via 2026 * {@link android.telephony.satellite.SatelliteDatagramCallback#onSatelliteDatagramReceived( 2027 * long, SatelliteDatagram, int, Consumer)} 2028 * 2029 * @param subId The subId of the subscription used for receiving datagrams. 2030 * @param callback The callback to get {@link SatelliteManager.SatelliteResult} of the request. 2031 */ pollPendingDatagrams(int subId, @NonNull IIntegerConsumer callback)2032 public void pollPendingDatagrams(int subId, @NonNull IIntegerConsumer callback) { 2033 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 2034 int error = evaluateOemSatelliteRequestAllowed(true); 2035 if (error != SATELLITE_RESULT_SUCCESS) { 2036 result.accept(error); 2037 return; 2038 } 2039 2040 final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext); 2041 mDatagramController.pollPendingSatelliteDatagrams(validSubId, result); 2042 } 2043 2044 /** 2045 * Send datagram over satellite. 2046 * 2047 * Gateway encodes SOS message or location sharing message into a datagram and passes it as 2048 * input to this method. Datagram received here will be passed down to modem without any 2049 * encoding or encryption. 2050 * 2051 * @param subId The subId of the subscription to send satellite datagrams for. 2052 * @param datagramType datagram type indicating whether the datagram is of type 2053 * SOS_SMS or LOCATION_SHARING. 2054 * @param datagram encoded gateway datagram which is encrypted by the caller. 2055 * Datagram will be passed down to modem without any encoding or encryption. 2056 * @param needFullScreenPointingUI this is used to indicate pointingUI app to open in 2057 * full screen mode. 2058 * @param callback The callback to get {@link SatelliteManager.SatelliteResult} of the request. 2059 */ sendDatagram(int subId, @SatelliteManager.DatagramType int datagramType, SatelliteDatagram datagram, boolean needFullScreenPointingUI, @NonNull IIntegerConsumer callback)2060 public void sendDatagram(int subId, @SatelliteManager.DatagramType int datagramType, 2061 SatelliteDatagram datagram, boolean needFullScreenPointingUI, 2062 @NonNull IIntegerConsumer callback) { 2063 plogd("sendSatelliteDatagram: subId: " + subId + " datagramType: " + datagramType 2064 + " needFullScreenPointingUI: " + needFullScreenPointingUI); 2065 2066 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 2067 int error = evaluateOemSatelliteRequestAllowed(true); 2068 if (error != SATELLITE_RESULT_SUCCESS) { 2069 result.accept(error); 2070 return; 2071 } 2072 2073 /** 2074 * TODO for NTN-based satellites: Check if satellite is acquired. 2075 */ 2076 if (mNeedsSatellitePointing) { 2077 2078 mPointingAppController.startPointingUI(needFullScreenPointingUI, mIsDemoModeEnabled, 2079 mIsEmergency); 2080 } 2081 2082 final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext); 2083 mDatagramController.sendSatelliteDatagram(validSubId, datagramType, datagram, 2084 needFullScreenPointingUI, result); 2085 } 2086 2087 /** 2088 * Request to get the time after which the satellite will be visible. 2089 * 2090 * @param subId The subId to get the time after which the satellite will be visible for. 2091 * @param result The result receiver that returns the time after which the satellite will 2092 * be visible if the request is successful or an error code if the request failed. 2093 */ requestTimeForNextSatelliteVisibility(int subId, @NonNull ResultReceiver result)2094 public void requestTimeForNextSatelliteVisibility(int subId, @NonNull ResultReceiver result) { 2095 int error = evaluateOemSatelliteRequestAllowed(true); 2096 if (error != SATELLITE_RESULT_SUCCESS) { 2097 result.send(error, null); 2098 return; 2099 } 2100 2101 sendRequestAsync(CMD_GET_TIME_SATELLITE_NEXT_VISIBLE, result, null); 2102 } 2103 2104 /** 2105 * Inform whether the device is aligned with satellite for demo mode. 2106 * 2107 * @param subId The subId of the subscription. 2108 * @param isAligned {@true} means device is aligned with the satellite, otherwise {@false}. 2109 */ setDeviceAlignedWithSatellite(@onNull int subId, @NonNull boolean isAligned)2110 public void setDeviceAlignedWithSatellite(@NonNull int subId, @NonNull boolean isAligned) { 2111 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2112 plogd("setDeviceAlignedWithSatellite: oemEnabledSatelliteFlag is disabled"); 2113 return; 2114 } 2115 2116 DemoSimulator.getInstance().setDeviceAlignedWithSatellite(isAligned); 2117 mDatagramController.setDeviceAlignedWithSatellite(isAligned); 2118 } 2119 2120 /** 2121 * Add a restriction reason for disallowing carrier supported satellite plmn scan and attach 2122 * by modem. After updating restriction list, evaluate if satellite should be enabled/disabled, 2123 * and request modem to enable/disable satellite accordingly if the desired state does not match 2124 * the current state. 2125 * 2126 * @param subId The subId of the subscription to request for. 2127 * @param reason Reason for disallowing satellite communication for carrier. 2128 * @param callback The callback to get the result of the request. 2129 */ addAttachRestrictionForCarrier(int subId, @SatelliteManager.SatelliteCommunicationRestrictionReason int reason, @NonNull IIntegerConsumer callback)2130 public void addAttachRestrictionForCarrier(int subId, 2131 @SatelliteManager.SatelliteCommunicationRestrictionReason int reason, 2132 @NonNull IIntegerConsumer callback) { 2133 if (DBG) logd("addAttachRestrictionForCarrier(" + subId + ", " + reason + ")"); 2134 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 2135 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 2136 result.accept(SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED); 2137 logd("addAttachRestrictionForCarrier: carrierEnabledSatelliteFlag is " 2138 + "disabled"); 2139 return; 2140 } 2141 2142 synchronized (mIsSatelliteEnabledLock) { 2143 if (mSatelliteAttachRestrictionForCarrierArray.getOrDefault( 2144 subId, Collections.emptySet()).isEmpty()) { 2145 mSatelliteAttachRestrictionForCarrierArray.put(subId, new HashSet<>()); 2146 } else if (mSatelliteAttachRestrictionForCarrierArray.get(subId).contains(reason)) { 2147 result.accept(SATELLITE_RESULT_SUCCESS); 2148 return; 2149 } 2150 mSatelliteAttachRestrictionForCarrierArray.get(subId).add(reason); 2151 } 2152 RequestHandleSatelliteAttachRestrictionForCarrierArgument request = 2153 new RequestHandleSatelliteAttachRestrictionForCarrierArgument(subId, reason, 2154 result); 2155 sendRequestAsync(CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE, request, 2156 SatelliteServiceUtils.getPhone(subId)); 2157 } 2158 2159 /** 2160 * Remove a restriction reason for disallowing carrier supported satellite plmn scan and attach 2161 * by modem. After updating restriction list, evaluate if satellite should be enabled/disabled, 2162 * and request modem to enable/disable satellite accordingly if the desired state does not match 2163 * the current state. 2164 * 2165 * @param subId The subId of the subscription to request for. 2166 * @param reason Reason for disallowing satellite communication. 2167 * @param callback The callback to get the result of the request. 2168 */ removeAttachRestrictionForCarrier(int subId, @SatelliteManager.SatelliteCommunicationRestrictionReason int reason, @NonNull IIntegerConsumer callback)2169 public void removeAttachRestrictionForCarrier(int subId, 2170 @SatelliteManager.SatelliteCommunicationRestrictionReason int reason, 2171 @NonNull IIntegerConsumer callback) { 2172 if (DBG) logd("removeAttachRestrictionForCarrier(" + subId + ", " + reason + ")"); 2173 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 2174 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 2175 result.accept(SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED); 2176 logd("removeAttachRestrictionForCarrier: carrierEnabledSatelliteFlag is " 2177 + "disabled"); 2178 return; 2179 } 2180 2181 synchronized (mIsSatelliteEnabledLock) { 2182 if (mSatelliteAttachRestrictionForCarrierArray.getOrDefault( 2183 subId, Collections.emptySet()).isEmpty() 2184 || !mSatelliteAttachRestrictionForCarrierArray.get(subId).contains(reason)) { 2185 result.accept(SATELLITE_RESULT_SUCCESS); 2186 return; 2187 } 2188 mSatelliteAttachRestrictionForCarrierArray.get(subId).remove(reason); 2189 } 2190 RequestHandleSatelliteAttachRestrictionForCarrierArgument request = 2191 new RequestHandleSatelliteAttachRestrictionForCarrierArgument(subId, reason, 2192 result); 2193 sendRequestAsync(CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE, request, 2194 SatelliteServiceUtils.getPhone(subId)); 2195 } 2196 2197 /** 2198 * Get reasons for disallowing satellite communication, as requested by 2199 * {@link #addAttachRestrictionForCarrier(int, int, IIntegerConsumer)}. 2200 * 2201 * @param subId The subId of the subscription to request for. 2202 * 2203 * @return Set of reasons for disallowing satellite attach for carrier. 2204 */ getAttachRestrictionReasonsForCarrier(int subId)2205 @NonNull public Set<Integer> getAttachRestrictionReasonsForCarrier(int subId) { 2206 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 2207 logd("getAttachRestrictionReasonsForCarrier: carrierEnabledSatelliteFlag is " 2208 + "disabled"); 2209 return new HashSet<>(); 2210 } 2211 synchronized (mIsSatelliteEnabledLock) { 2212 Set<Integer> resultSet = 2213 mSatelliteAttachRestrictionForCarrierArray.get(subId); 2214 if (resultSet == null) { 2215 return new HashSet<>(); 2216 } 2217 return new HashSet<>(resultSet); 2218 } 2219 } 2220 2221 /** 2222 * Request to get the signal strength of the satellite connection. 2223 * 2224 * @param subId The subId of the subscription to request for. 2225 * @param result Result receiver to get the error code of the request and the current signal 2226 * strength of the satellite connection. 2227 */ requestNtnSignalStrength(int subId, @NonNull ResultReceiver result)2228 public void requestNtnSignalStrength(int subId, @NonNull ResultReceiver result) { 2229 if (DBG) plogd("requestNtnSignalStrength()"); 2230 2231 int error = evaluateOemSatelliteRequestAllowed(true); 2232 if (error != SATELLITE_RESULT_SUCCESS) { 2233 result.send(error, null); 2234 return; 2235 } 2236 2237 /* In case cache is available, it is not needed to request non-terrestrial signal strength 2238 to modem */ 2239 synchronized (mNtnSignalsStrengthLock) { 2240 if (mNtnSignalStrength.getLevel() != NTN_SIGNAL_STRENGTH_NONE) { 2241 Bundle bundle = new Bundle(); 2242 bundle.putParcelable(KEY_NTN_SIGNAL_STRENGTH, mNtnSignalStrength); 2243 result.send(SATELLITE_RESULT_SUCCESS, bundle); 2244 return; 2245 } 2246 } 2247 2248 Phone phone = SatelliteServiceUtils.getPhone(); 2249 sendRequestAsync(CMD_REQUEST_NTN_SIGNAL_STRENGTH, result, phone); 2250 } 2251 2252 /** 2253 * Registers for NTN signal strength changed from satellite modem. If the registration operation 2254 * is not successful, a {@link ServiceSpecificException} that contains 2255 * {@link SatelliteManager.SatelliteResult} will be thrown. 2256 * 2257 * @param subId The id of the subscription to request for. 2258 * @param callback The callback to handle the NTN signal strength changed event. If the 2259 * operation is successful, {@link INtnSignalStrengthCallback#onNtnSignalStrengthChanged( 2260 * NtnSignalStrength)} will return an instance of {@link NtnSignalStrength} with a value of 2261 * {@link NtnSignalStrength.NtnSignalStrengthLevel} when the signal strength of non-terrestrial 2262 * network has changed. 2263 * 2264 * @throws ServiceSpecificException If the callback registration operation fails. 2265 */ registerForNtnSignalStrengthChanged(int subId, @NonNull INtnSignalStrengthCallback callback)2266 public void registerForNtnSignalStrengthChanged(int subId, 2267 @NonNull INtnSignalStrengthCallback callback) throws RemoteException { 2268 if (DBG) plogd("registerForNtnSignalStrengthChanged()"); 2269 2270 int error = evaluateOemSatelliteRequestAllowed(true); 2271 if (error == SATELLITE_RESULT_SUCCESS) { 2272 mNtnSignalStrengthChangedListeners.put(callback.asBinder(), callback); 2273 synchronized (mNtnSignalsStrengthLock) { 2274 try { 2275 callback.onNtnSignalStrengthChanged(mNtnSignalStrength); 2276 plogd("registerForNtnSignalStrengthChanged: " + mNtnSignalStrength); 2277 } catch (RemoteException ex) { 2278 ploge("registerForNtnSignalStrengthChanged: RemoteException ex=" 2279 + ex); 2280 } 2281 } 2282 } else { 2283 throw new RemoteException(new IllegalStateException("registration fails: " + error)); 2284 } 2285 } 2286 2287 /** 2288 * Unregisters for NTN signal strength changed from satellite modem. 2289 * If callback was not registered before, the request will be ignored. 2290 * 2291 * @param subId The id of the subscription to unregister for listening NTN signal strength 2292 * changed event. 2293 * @param callback The callback that was passed to 2294 * {@link #registerForNtnSignalStrengthChanged(int, INtnSignalStrengthCallback)} 2295 */ unregisterForNtnSignalStrengthChanged( int subId, @NonNull INtnSignalStrengthCallback callback)2296 public void unregisterForNtnSignalStrengthChanged( 2297 int subId, @NonNull INtnSignalStrengthCallback callback) { 2298 if (DBG) plogd("unregisterForNtnSignalStrengthChanged()"); 2299 2300 int error = evaluateOemSatelliteRequestAllowed(true); 2301 if (error == SATELLITE_RESULT_SUCCESS) { 2302 mNtnSignalStrengthChangedListeners.remove(callback.asBinder()); 2303 } 2304 } 2305 2306 /** 2307 * Registers for satellite capabilities change event from the satellite service. 2308 * 2309 * @param subId The id of the subscription to request for. 2310 * @param callback The callback to handle the satellite capabilities changed event. 2311 * 2312 * @return The {@link SatelliteManager.SatelliteResult} result of the operation. 2313 */ registerForCapabilitiesChanged( int subId, @NonNull ISatelliteCapabilitiesCallback callback)2314 @SatelliteManager.SatelliteResult public int registerForCapabilitiesChanged( 2315 int subId, @NonNull ISatelliteCapabilitiesCallback callback) { 2316 if (DBG) plogd("registerForCapabilitiesChanged()"); 2317 2318 int error = evaluateOemSatelliteRequestAllowed(true); 2319 if (error != SATELLITE_RESULT_SUCCESS) return error; 2320 2321 mSatelliteCapabilitiesChangedListeners.put(callback.asBinder(), callback); 2322 return SATELLITE_RESULT_SUCCESS; 2323 } 2324 2325 /** 2326 * Unregisters for satellite capabilities change event from the satellite service. 2327 * If callback was not registered before, the request will be ignored. 2328 * 2329 * @param subId The id of the subscription to unregister for listening satellite capabilities 2330 * changed event. 2331 * @param callback The callback that was passed to 2332 * {@link #registerForCapabilitiesChanged(int, ISatelliteCapabilitiesCallback)} 2333 */ unregisterForCapabilitiesChanged( int subId, @NonNull ISatelliteCapabilitiesCallback callback)2334 public void unregisterForCapabilitiesChanged( 2335 int subId, @NonNull ISatelliteCapabilitiesCallback callback) { 2336 if (DBG) plogd("unregisterForCapabilitiesChanged()"); 2337 2338 int error = evaluateOemSatelliteRequestAllowed(true); 2339 if (error == SATELLITE_RESULT_SUCCESS) { 2340 mSatelliteCapabilitiesChangedListeners.remove(callback.asBinder()); 2341 } 2342 } 2343 2344 /** 2345 * Registers for the satellite supported state changed. 2346 * 2347 * @param subId The subId of the subscription to register for supported state changed. 2348 * @param callback The callback to handle the satellite supported state changed event. 2349 * 2350 * @return The {@link SatelliteManager.SatelliteResult} result of the operation. 2351 */ registerForSatelliteSupportedStateChanged( int subId, @NonNull ISatelliteSupportedStateCallback callback)2352 @SatelliteManager.SatelliteResult public int registerForSatelliteSupportedStateChanged( 2353 int subId, @NonNull ISatelliteSupportedStateCallback callback) { 2354 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2355 plogd("registerForSatelliteSupportedStateChanged: oemEnabledSatelliteFlag is disabled"); 2356 return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED; 2357 } 2358 2359 mSatelliteSupportedStateChangedListeners.put(callback.asBinder(), callback); 2360 return SATELLITE_RESULT_SUCCESS; 2361 } 2362 2363 /** 2364 * Unregisters for the satellite supported state changed. 2365 * If callback was not registered before, the request will be ignored. 2366 * 2367 * @param subId The subId of the subscription to unregister for supported state changed. 2368 * @param callback The callback that was passed to 2369 * {@link #registerForSatelliteSupportedStateChanged(int, ISatelliteSupportedStateCallback)}. 2370 */ unregisterForSatelliteSupportedStateChanged( int subId, @NonNull ISatelliteSupportedStateCallback callback)2371 public void unregisterForSatelliteSupportedStateChanged( 2372 int subId, @NonNull ISatelliteSupportedStateCallback callback) { 2373 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2374 plogd("unregisterForSatelliteSupportedStateChanged: " 2375 + "oemEnabledSatelliteFlag is disabled"); 2376 return; 2377 } 2378 mSatelliteSupportedStateChangedListeners.remove(callback.asBinder()); 2379 } 2380 2381 /** 2382 * This API can be used by only CTS to update satellite vendor service package name. 2383 * 2384 * @param servicePackageName The package name of the satellite vendor service. 2385 * @return {@code true} if the satellite vendor service is set successfully, 2386 * {@code false} otherwise. 2387 */ setSatelliteServicePackageName(@ullable String servicePackageName)2388 public boolean setSatelliteServicePackageName(@Nullable String servicePackageName) { 2389 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2390 plogd("setSatelliteServicePackageName: oemEnabledSatelliteFlag is disabled"); 2391 return false; 2392 } 2393 if (!isMockModemAllowed()) { 2394 plogd("setSatelliteServicePackageName: mock modem not allowed"); 2395 return false; 2396 } 2397 2398 // Cached states need to be cleared whenever switching satellite vendor services. 2399 plogd("setSatelliteServicePackageName: Resetting cached states"); 2400 synchronized (mIsSatelliteSupportedLock) { 2401 mIsSatelliteSupported = null; 2402 } 2403 synchronized (mSatelliteViaOemProvisionLock) { 2404 mIsSatelliteViaOemProvisioned = null; 2405 } 2406 synchronized (mIsSatelliteEnabledLock) { 2407 mIsSatelliteEnabled = null; 2408 } 2409 synchronized (mSatelliteCapabilitiesLock) { 2410 mSatelliteCapabilities = null; 2411 } 2412 mSatelliteModemInterface.setSatelliteServicePackageName(servicePackageName); 2413 return true; 2414 } 2415 2416 /** 2417 * This API can be used by only CTS to update the timeout duration in milliseconds that 2418 * satellite should stay at listening mode to wait for the next incoming page before disabling 2419 * listening mode. 2420 * 2421 * @param timeoutMillis The timeout duration in millisecond. 2422 * @return {@code true} if the timeout duration is set successfully, {@code false} otherwise. 2423 */ setSatelliteListeningTimeoutDuration(long timeoutMillis)2424 public boolean setSatelliteListeningTimeoutDuration(long timeoutMillis) { 2425 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2426 plogd("setSatelliteListeningTimeoutDuration: oemEnabledSatelliteFlag is disabled"); 2427 return false; 2428 } 2429 if (mSatelliteSessionController == null) { 2430 ploge("mSatelliteSessionController is not initialized yet"); 2431 return false; 2432 } 2433 return mSatelliteSessionController.setSatelliteListeningTimeoutDuration(timeoutMillis); 2434 } 2435 2436 /** 2437 * This API can be used by only CTS to override timeout durations used by DatagramController 2438 * module. 2439 * 2440 * @param timeoutMillis The timeout duration in millisecond. 2441 * @return {@code true} if the timeout duration is set successfully, {@code false} otherwise. 2442 */ setDatagramControllerTimeoutDuration( boolean reset, int timeoutType, long timeoutMillis)2443 public boolean setDatagramControllerTimeoutDuration( 2444 boolean reset, int timeoutType, long timeoutMillis) { 2445 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2446 plogd("setDatagramControllerTimeoutDuration: oemEnabledSatelliteFlag is disabled"); 2447 return false; 2448 } 2449 plogd("setDatagramControllerTimeoutDuration: reset=" + reset + ", timeoutType=" 2450 + timeoutType + ", timeoutMillis=" + timeoutMillis); 2451 return mDatagramController.setDatagramControllerTimeoutDuration( 2452 reset, timeoutType, timeoutMillis); 2453 } 2454 2455 /** 2456 * This API can be used by only CTS to override the boolean configs used by the 2457 * DatagramController module. 2458 * 2459 * @param enable Whether to enable or disable boolean config. 2460 * @return {@code true} if the boolean config is set successfully, {@code false} otherwise. 2461 */ setDatagramControllerBooleanConfig( boolean reset, int booleanType, boolean enable)2462 public boolean setDatagramControllerBooleanConfig( 2463 boolean reset, int booleanType, boolean enable) { 2464 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2465 logd("setDatagramControllerBooleanConfig: oemEnabledSatelliteFlag is disabled"); 2466 return false; 2467 } 2468 logd("setDatagramControllerBooleanConfig: reset=" + reset + ", booleanType=" 2469 + booleanType + ", enable=" + enable); 2470 return mDatagramController.setDatagramControllerBooleanConfig( 2471 reset, booleanType, enable); 2472 } 2473 2474 /** 2475 * This API can be used by only CTS to override timeout durations used by SatelliteController 2476 * module. 2477 * 2478 * @param timeoutMillis The timeout duration in millisecond. 2479 * @return {@code true} if the timeout duration is set successfully, {@code false} otherwise. 2480 */ setSatelliteControllerTimeoutDuration( boolean reset, int timeoutType, long timeoutMillis)2481 public boolean setSatelliteControllerTimeoutDuration( 2482 boolean reset, int timeoutType, long timeoutMillis) { 2483 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2484 plogd("setSatelliteControllerTimeoutDuration: oemEnabledSatelliteFlag is disabled"); 2485 return false; 2486 } 2487 if (!isMockModemAllowed()) { 2488 plogd("setSatelliteControllerTimeoutDuration: mock modem is not allowed"); 2489 return false; 2490 } 2491 plogd("setSatelliteControllerTimeoutDuration: reset=" + reset + ", timeoutType=" 2492 + timeoutType + ", timeoutMillis=" + timeoutMillis); 2493 if (timeoutType == TIMEOUT_TYPE_WAIT_FOR_SATELLITE_ENABLING_RESPONSE) { 2494 if (reset) { 2495 mWaitTimeForSatelliteEnablingResponse = 2496 getWaitForSatelliteEnablingResponseTimeoutMillis(); 2497 } else { 2498 mWaitTimeForSatelliteEnablingResponse = timeoutMillis; 2499 } 2500 plogd("mWaitTimeForSatelliteEnablingResponse=" + mWaitTimeForSatelliteEnablingResponse); 2501 } else if (timeoutType == TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS) { 2502 if (reset) { 2503 mDemoPointingAlignedDurationMillis = 2504 getDemoPointingAlignedDurationMillisFromResources(); 2505 } else { 2506 mDemoPointingAlignedDurationMillis = timeoutMillis; 2507 } 2508 } else if (timeoutType == TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS) { 2509 if (reset) { 2510 mDemoPointingNotAlignedDurationMillis = 2511 getDemoPointingNotAlignedDurationMillisFromResources(); 2512 } else { 2513 mDemoPointingNotAlignedDurationMillis = timeoutMillis; 2514 } 2515 } else { 2516 plogw("Invalid timeoutType=" + timeoutType); 2517 return false; 2518 } 2519 return true; 2520 } 2521 2522 /** 2523 * This API can be used by only CTS to update satellite gateway service package name. 2524 * 2525 * @param servicePackageName The package name of the satellite gateway service. 2526 * @return {@code true} if the satellite gateway service is set successfully, 2527 * {@code false} otherwise. 2528 */ setSatelliteGatewayServicePackageName(@ullable String servicePackageName)2529 public boolean setSatelliteGatewayServicePackageName(@Nullable String servicePackageName) { 2530 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2531 plogd("setSatelliteGatewayServicePackageName: oemEnabledSatelliteFlag is disabled"); 2532 return false; 2533 } 2534 if (mSatelliteSessionController == null) { 2535 ploge("mSatelliteSessionController is not initialized yet"); 2536 return false; 2537 } 2538 return mSatelliteSessionController.setSatelliteGatewayServicePackageName( 2539 servicePackageName); 2540 } 2541 2542 /** 2543 * This API can be used by only CTS to update satellite pointing UI app package and class names. 2544 * 2545 * @param packageName The package name of the satellite pointing UI app. 2546 * @param className The class name of the satellite pointing UI app. 2547 * @return {@code true} if the satellite pointing UI app package and class is set successfully, 2548 * {@code false} otherwise. 2549 */ setSatellitePointingUiClassName( @ullable String packageName, @Nullable String className)2550 public boolean setSatellitePointingUiClassName( 2551 @Nullable String packageName, @Nullable String className) { 2552 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2553 plogd("setSatellitePointingUiClassName: oemEnabledSatelliteFlag is disabled"); 2554 return false; 2555 } 2556 return mPointingAppController.setSatellitePointingUiClassName(packageName, className); 2557 } 2558 2559 /** 2560 * This API can be used in only testing to override connectivity status in monitoring emergency 2561 * calls and sending EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer. 2562 * 2563 * @param handoverType The type of handover from emergency call to satellite messaging. Use one 2564 * of the following values to enable the override: 2565 * 0 - EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS 2566 * 1 - EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911 2567 * To disable the override, use -1 for handoverType. 2568 * @param delaySeconds The event EVENT_DISPLAY_EMERGENCY_MESSAGE will be sent to Dialer 2569 * delaySeconds after the emergency call starts. 2570 * @return {@code true} if the handover type is set successfully, {@code false} otherwise. 2571 */ setEmergencyCallToSatelliteHandoverType(int handoverType, int delaySeconds)2572 public boolean setEmergencyCallToSatelliteHandoverType(int handoverType, int delaySeconds) { 2573 if (!isMockModemAllowed()) { 2574 ploge("setEmergencyCallToSatelliteHandoverType: mock modem not allowed"); 2575 return false; 2576 } 2577 if (isHandoverTypeValid(handoverType)) { 2578 mEnforcedEmergencyCallToSatelliteHandoverType = handoverType; 2579 mDelayInSendingEventDisplayEmergencyMessage = delaySeconds > 0 ? delaySeconds : 0; 2580 } else { 2581 mEnforcedEmergencyCallToSatelliteHandoverType = 2582 INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE; 2583 mDelayInSendingEventDisplayEmergencyMessage = 0; 2584 } 2585 return true; 2586 } 2587 2588 /** 2589 * This API can be used in only testing to override oem-enabled satellite provision status. 2590 * 2591 * @param reset {@code true} mean the overriding status should not be used, {@code false} 2592 * otherwise. 2593 * @param isProvisioned The overriding provision status. 2594 * @return {@code true} if the provision status is set successfully, {@code false} otherwise. 2595 */ setOemEnabledSatelliteProvisionStatus(boolean reset, boolean isProvisioned)2596 public boolean setOemEnabledSatelliteProvisionStatus(boolean reset, boolean isProvisioned) { 2597 if (!isMockModemAllowed()) { 2598 ploge("setOemEnabledSatelliteProvisionStatus: mock modem not allowed"); 2599 return false; 2600 } 2601 synchronized (mSatelliteViaOemProvisionLock) { 2602 if (reset) { 2603 mOverriddenIsSatelliteViaOemProvisioned = null; 2604 } else { 2605 mOverriddenIsSatelliteViaOemProvisioned = isProvisioned; 2606 } 2607 } 2608 return true; 2609 } 2610 2611 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) getEnforcedEmergencyCallToSatelliteHandoverType()2612 protected int getEnforcedEmergencyCallToSatelliteHandoverType() { 2613 return mEnforcedEmergencyCallToSatelliteHandoverType; 2614 } 2615 2616 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) getDelayInSendingEventDisplayEmergencyMessage()2617 protected int getDelayInSendingEventDisplayEmergencyMessage() { 2618 return mDelayInSendingEventDisplayEmergencyMessage; 2619 } 2620 isHandoverTypeValid(int handoverType)2621 private boolean isHandoverTypeValid(int handoverType) { 2622 if (handoverType == EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS 2623 || handoverType == EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911) { 2624 return true; 2625 } 2626 return false; 2627 } 2628 2629 /** 2630 * This function is used by {@link SatelliteModemInterface} to notify 2631 * {@link SatelliteController} that the satellite vendor service was just connected. 2632 * <p> 2633 * {@link SatelliteController} will send requests to satellite modem to check whether it support 2634 * satellite and whether it is provisioned. {@link SatelliteController} will use these cached 2635 * values to serve requests from its clients. 2636 * <p> 2637 * Because satellite vendor service might have just come back from a crash, we need to disable 2638 * the satellite modem so that resources will be cleaned up and internal states will be reset. 2639 */ 2640 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) onSatelliteServiceConnected()2641 public void onSatelliteServiceConnected() { 2642 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2643 plogd("onSatelliteServiceConnected: oemEnabledSatelliteFlag is disabled"); 2644 return; 2645 } 2646 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 2647 synchronized (mIsSatelliteSupportedLock) { 2648 if (mIsSatelliteSupported == null) { 2649 ResultReceiver receiver = new ResultReceiver(this) { 2650 @Override 2651 protected void onReceiveResult( 2652 int resultCode, Bundle resultData) { 2653 plogd("onSatelliteServiceConnected.requestIsSatelliteSupported:" 2654 + " resultCode=" + resultCode); 2655 } 2656 }; 2657 requestIsSatelliteSupported( 2658 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, receiver); 2659 } 2660 } 2661 } else { 2662 plogd("onSatelliteServiceConnected: Satellite vendor service is not supported." 2663 + " Ignored the event"); 2664 } 2665 } 2666 2667 /** 2668 * This function is used by {@link com.android.internal.telephony.ServiceStateTracker} to notify 2669 * {@link SatelliteController} that it has received a request to power off the cellular radio 2670 * modem. {@link SatelliteController} will then power off the satellite modem. 2671 */ onCellularRadioPowerOffRequested()2672 public void onCellularRadioPowerOffRequested() { 2673 logd("onCellularRadioPowerOffRequested()"); 2674 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2675 plogd("onCellularRadioPowerOffRequested: oemEnabledSatelliteFlag is disabled"); 2676 return; 2677 } 2678 2679 synchronized (mIsRadioOnLock) { 2680 mIsRadioOn = false; 2681 } 2682 requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, 2683 false /* enableSatellite */, false /* enableDemoMode */, false /* isEmergency */, 2684 new IIntegerConsumer.Stub() { 2685 @Override 2686 public void accept(int result) { 2687 plogd("onRadioPowerOffRequested: requestSatelliteEnabled result=" + result); 2688 } 2689 }); 2690 } 2691 2692 /** 2693 * @return {@code true} if satellite is supported via OEM on the device, 2694 * {@code false} otherwise. 2695 */ isSatelliteSupportedViaOem()2696 public boolean isSatelliteSupportedViaOem() { 2697 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2698 plogd("isSatelliteSupported: oemEnabledSatelliteFlag is disabled"); 2699 return false; 2700 } 2701 Boolean supported = isSatelliteSupportedViaOemInternal(); 2702 return (supported != null ? supported : false); 2703 } 2704 2705 /** 2706 * @param subId Subscription ID. 2707 * @return The list of satellite PLMNs used for connecting to satellite networks. 2708 */ 2709 @NonNull getSatellitePlmnsForCarrier(int subId)2710 public List<String> getSatellitePlmnsForCarrier(int subId) { 2711 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 2712 logd("getSatellitePlmnsForCarrier: carrierEnabledSatelliteFlag is disabled"); 2713 return new ArrayList<>(); 2714 } 2715 2716 if (!isSatelliteSupportedViaCarrier(subId)) { 2717 logd("Satellite for carrier is not supported."); 2718 return new ArrayList<>(); 2719 } 2720 2721 synchronized (mSupportedSatelliteServicesLock) { 2722 return mMergedPlmnListPerCarrier.get(subId, new ArrayList<>()).stream().toList(); 2723 } 2724 } 2725 2726 /** 2727 * @param subId Subscription ID. 2728 * @param plmn The satellite plmn. 2729 * @return The list of services supported by the carrier associated with the {@code subId} for 2730 * the satellite network {@code plmn}. 2731 */ 2732 @NonNull getSupportedSatelliteServices(int subId, String plmn)2733 public List<Integer> getSupportedSatelliteServices(int subId, String plmn) { 2734 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 2735 logd("getSupportedSatelliteServices: carrierEnabledSatelliteFlag is disabled"); 2736 return new ArrayList<>(); 2737 } 2738 synchronized (mSupportedSatelliteServicesLock) { 2739 if (mSatelliteServicesSupportedByCarriers.containsKey(subId)) { 2740 Map<String, Set<Integer>> supportedServices = 2741 mSatelliteServicesSupportedByCarriers.get(subId); 2742 if (supportedServices != null && supportedServices.containsKey(plmn)) { 2743 return new ArrayList<>(supportedServices.get(plmn)); 2744 } else { 2745 loge("getSupportedSatelliteServices: subId=" + subId + ", supportedServices " 2746 + "does not contain key plmn=" + plmn); 2747 } 2748 } else { 2749 loge("getSupportedSatelliteServices: mSatelliteServicesSupportedByCarriers does " 2750 + "not contain key subId=" + subId); 2751 } 2752 2753 /* Returns default capabilities when carrier config does not contain service 2754 capabilities for the given plmn */ 2755 PersistableBundle config = getPersistableBundle(subId); 2756 int [] defaultCapabilities = config.getIntArray( 2757 KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY); 2758 if (defaultCapabilities == null) { 2759 logd("getSupportedSatelliteServices: defaultCapabilities is null"); 2760 return new ArrayList<>(); 2761 } 2762 List<Integer> capabilitiesList = Arrays.stream( 2763 defaultCapabilities).boxed().collect(Collectors.toList()); 2764 logd("getSupportedSatelliteServices: subId=" + subId 2765 + ", supportedServices does not contain key plmn=" + plmn 2766 + ", return default values " + capabilitiesList); 2767 return capabilitiesList; 2768 } 2769 } 2770 2771 /** 2772 * Check whether satellite modem has to attach to a satellite network before sending/receiving 2773 * datagrams. 2774 * 2775 * @return {@code true} if satellite attach is required, {@code false} otherwise. 2776 */ isSatelliteAttachRequired()2777 public boolean isSatelliteAttachRequired() { 2778 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2779 plogd("isSatelliteAttachRequired: oemEnabledSatelliteFlag is disabled"); 2780 return false; 2781 } 2782 2783 synchronized (mSatelliteCapabilitiesLock) { 2784 if (mSatelliteCapabilities == null) { 2785 ploge("isSatelliteAttachRequired: mSatelliteCapabilities is null"); 2786 return false; 2787 } 2788 if (mSatelliteCapabilities.getSupportedRadioTechnologies().contains( 2789 SatelliteManager.NT_RADIO_TECHNOLOGY_NB_IOT_NTN)) { 2790 return true; 2791 } 2792 return false; 2793 } 2794 } 2795 2796 /** 2797 * @return {@code true} if satellite is supported via carrier by any subscription on the device, 2798 * {@code false} otherwise. 2799 */ isSatelliteSupportedViaCarrier()2800 public boolean isSatelliteSupportedViaCarrier() { 2801 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 2802 logd("isSatelliteSupportedViaCarrier: carrierEnabledSatelliteFlag is disabled"); 2803 return false; 2804 } 2805 for (Phone phone : PhoneFactory.getPhones()) { 2806 if (isSatelliteSupportedViaCarrier(phone.getSubId())) { 2807 return true; 2808 } 2809 } 2810 return false; 2811 } 2812 2813 /** 2814 * @return {@code true} if satellite emergency messaging is supported via carrier by any 2815 * subscription on the device, {@code false} otherwise. 2816 */ isSatelliteEmergencyMessagingSupportedViaCarrier()2817 public boolean isSatelliteEmergencyMessagingSupportedViaCarrier() { 2818 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 2819 logd("isSatelliteEmergencyMessagingSupportedViaCarrier: carrierEnabledSatelliteFlag is" 2820 + " disabled"); 2821 return false; 2822 } 2823 for (Phone phone : PhoneFactory.getPhones()) { 2824 if (isSatelliteEmergencyMessagingSupportedViaCarrier(phone.getSubId())) { 2825 return true; 2826 } 2827 } 2828 return false; 2829 } 2830 isSatelliteEmergencyMessagingSupportedViaCarrier(int subId)2831 private boolean isSatelliteEmergencyMessagingSupportedViaCarrier(int subId) { 2832 if (!isSatelliteSupportedViaCarrier(subId)) { 2833 return false; 2834 } 2835 PersistableBundle config = getPersistableBundle(subId); 2836 return config.getBoolean(KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL); 2837 } 2838 2839 /** 2840 * @return {@code Pair<true, subscription ID>} if any subscription on the device is connected to 2841 * satellite, {@code Pair<false, null>} otherwise. 2842 */ isUsingNonTerrestrialNetworkViaCarrier()2843 private Pair<Boolean, Integer> isUsingNonTerrestrialNetworkViaCarrier() { 2844 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 2845 logd("isUsingNonTerrestrialNetwork: carrierEnabledSatelliteFlag is disabled"); 2846 return new Pair<>(false, null); 2847 } 2848 for (Phone phone : PhoneFactory.getPhones()) { 2849 ServiceState serviceState = phone.getServiceState(); 2850 if (serviceState != null && serviceState.isUsingNonTerrestrialNetwork()) { 2851 return new Pair<>(true, phone.getSubId()); 2852 } 2853 } 2854 return new Pair<>(false, null); 2855 } 2856 2857 /** 2858 * @return {@code true} if the device is connected to satellite via any carrier within the 2859 * {@link CarrierConfigManager#KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT} 2860 * duration, {@code false} otherwise. 2861 */ isSatelliteConnectedViaCarrierWithinHysteresisTime()2862 public boolean isSatelliteConnectedViaCarrierWithinHysteresisTime() { 2863 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 2864 logd("isSatelliteConnectedViaCarrierWithinHysteresisTime: carrierEnabledSatelliteFlag" 2865 + " is disabled"); 2866 return false; 2867 } 2868 if (isUsingNonTerrestrialNetworkViaCarrier().first) { 2869 return true; 2870 } 2871 for (Phone phone : PhoneFactory.getPhones()) { 2872 if (isInSatelliteModeForCarrierRoaming(phone)) { 2873 logd("isSatelliteConnectedViaCarrierWithinHysteresisTime: " 2874 + "subId:" + phone.getSubId() 2875 + " is connected to satellite within hysteresis time"); 2876 return true; 2877 } 2878 } 2879 return false; 2880 } 2881 2882 /** 2883 * Get whether device is connected to satellite via carrier. 2884 * 2885 * @param phone phone object 2886 * @return {@code true} if the device is connected to satellite using the phone within the 2887 * {@link CarrierConfigManager#KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT} 2888 * duration, {@code false} otherwise. 2889 */ isInSatelliteModeForCarrierRoaming(@ullable Phone phone)2890 public boolean isInSatelliteModeForCarrierRoaming(@Nullable Phone phone) { 2891 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 2892 logd("isInSatelliteModeForCarrierRoaming: carrierEnabledSatelliteFlag is disabled"); 2893 return false; 2894 } 2895 2896 if (phone == null) { 2897 return false; 2898 } 2899 2900 int subId = phone.getSubId(); 2901 if (!isSatelliteSupportedViaCarrier(subId)) { 2902 return false; 2903 } 2904 2905 ServiceState serviceState = phone.getServiceState(); 2906 if (serviceState == null) { 2907 return false; 2908 } 2909 2910 if (serviceState.isUsingNonTerrestrialNetwork()) { 2911 return true; 2912 } 2913 2914 if (getWwanIsInService(serviceState)) { 2915 // Device is connected to terrestrial network which has coverage 2916 resetCarrierRoamingSatelliteModeParams(subId); 2917 return false; 2918 } 2919 2920 synchronized (mSatelliteConnectedLock) { 2921 Long lastDisconnectedTime = mLastSatelliteDisconnectedTimesMillis.get(subId); 2922 long satelliteConnectionHysteresisTime = 2923 getSatelliteConnectionHysteresisTimeMillis(subId); 2924 if (lastDisconnectedTime != null 2925 && (getElapsedRealtime() - lastDisconnectedTime) 2926 <= satelliteConnectionHysteresisTime) { 2927 logd("isInSatelliteModeForCarrierRoaming: " + "subId:" + subId 2928 + " is connected to satellite within hysteresis time"); 2929 return true; 2930 } else { 2931 resetCarrierRoamingSatelliteModeParams(subId); 2932 return false; 2933 } 2934 } 2935 } 2936 2937 /** 2938 * Return capabilities of carrier roaming satellite network. 2939 * 2940 * @param phone phone object 2941 * @return The list of services supported by the carrier associated with the {@code subId} 2942 */ 2943 @NonNull getCapabilitiesForCarrierRoamingSatelliteMode(Phone phone)2944 public List<Integer> getCapabilitiesForCarrierRoamingSatelliteMode(Phone phone) { 2945 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 2946 logd("getCapabilitiesForCarrierRoamingSatelliteMode: carrierEnabledSatelliteFlag" 2947 + " is disabled"); 2948 return new ArrayList<>(); 2949 } 2950 2951 synchronized (mSatelliteConnectedLock) { 2952 int subId = phone.getSubId(); 2953 if (mSatModeCapabilitiesForCarrierRoaming.containsKey(subId)) { 2954 return mSatModeCapabilitiesForCarrierRoaming.get(subId); 2955 } 2956 } 2957 2958 return new ArrayList<>(); 2959 } 2960 2961 /** 2962 * Request to get the {@link SatelliteSessionStats} of the satellite service. 2963 * 2964 * @param subId The subId of the subscription to the satellite session stats for. 2965 * @param result The result receiver that returns the {@link SatelliteSessionStats} 2966 * if the request is successful or an error code if the request failed. 2967 */ requestSatelliteSessionStats(int subId, @NonNull ResultReceiver result)2968 public void requestSatelliteSessionStats(int subId, @NonNull ResultReceiver result) { 2969 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2970 return; 2971 } 2972 mSessionMetricsStats.requestSatelliteSessionStats(subId, result); 2973 } 2974 2975 /** 2976 * Get the carrier-enabled emergency call wait for connection timeout millis 2977 */ getCarrierEmergencyCallWaitForConnectionTimeoutMillis()2978 public long getCarrierEmergencyCallWaitForConnectionTimeoutMillis() { 2979 long maxTimeoutMillis = 0; 2980 for (Phone phone : PhoneFactory.getPhones()) { 2981 if (!isSatelliteEmergencyMessagingSupportedViaCarrier(phone.getSubId())) { 2982 continue; 2983 } 2984 2985 int timeoutMillis = 2986 getCarrierEmergencyCallWaitForConnectionTimeoutMillis(phone.getSubId()); 2987 // Prioritize getting the timeout duration from the phone that is in satellite mode 2988 // with carrier roaming 2989 if (isInSatelliteModeForCarrierRoaming(phone)) { 2990 return timeoutMillis; 2991 } 2992 if (maxTimeoutMillis < timeoutMillis) { 2993 maxTimeoutMillis = timeoutMillis; 2994 } 2995 } 2996 if (maxTimeoutMillis != 0) { 2997 return maxTimeoutMillis; 2998 } 2999 return DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS; 3000 } 3001 getCarrierEmergencyCallWaitForConnectionTimeoutMillis(int subId)3002 private int getCarrierEmergencyCallWaitForConnectionTimeoutMillis(int subId) { 3003 PersistableBundle config = getPersistableBundle(subId); 3004 return config.getInt(KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT); 3005 } 3006 3007 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) getElapsedRealtime()3008 protected long getElapsedRealtime() { 3009 return SystemClock.elapsedRealtime(); 3010 } 3011 3012 /** 3013 * Register the handler for SIM Refresh notifications. 3014 * @param handler Handler for notification message. 3015 * @param what User-defined message code. 3016 */ registerIccRefresh(Handler handler, int what)3017 public void registerIccRefresh(Handler handler, int what) { 3018 for (Phone phone : PhoneFactory.getPhones()) { 3019 CommandsInterface ci = phone.mCi; 3020 ci.registerForIccRefresh(handler, what, null); 3021 } 3022 } 3023 3024 /** 3025 * Unregister the handler for SIM Refresh notifications. 3026 * @param handler Handler for notification message. 3027 */ unRegisterIccRefresh(Handler handler)3028 public void unRegisterIccRefresh(Handler handler) { 3029 for (Phone phone : PhoneFactory.getPhones()) { 3030 CommandsInterface ci = phone.mCi; 3031 ci.unregisterForIccRefresh(handler); 3032 } 3033 } 3034 3035 /** 3036 * To use the satellite service, update the EntitlementStatus and the PlmnAllowedList after 3037 * receiving the satellite configuration from the entitlement server. If satellite 3038 * entitlement is enabled, enable satellite for the carrier. Otherwise, disable satellite. 3039 * 3040 * @param subId subId 3041 * @param entitlementEnabled {@code true} Satellite service enabled 3042 * @param allowedPlmnList plmn allowed list to use the satellite service 3043 * @param barredPlmnList plmn barred list to pass the modem 3044 * @param callback callback for accept 3045 */ onSatelliteEntitlementStatusUpdated(int subId, boolean entitlementEnabled, @Nullable List<String> allowedPlmnList, @Nullable List<String> barredPlmnList, @Nullable IIntegerConsumer callback)3046 public void onSatelliteEntitlementStatusUpdated(int subId, boolean entitlementEnabled, 3047 @Nullable List<String> allowedPlmnList, @Nullable List<String> barredPlmnList, 3048 @Nullable IIntegerConsumer callback) { 3049 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 3050 logd("onSatelliteEntitlementStatusUpdated: carrierEnabledSatelliteFlag is not enabled"); 3051 return; 3052 } 3053 3054 if (callback == null) { 3055 callback = new IIntegerConsumer.Stub() { 3056 @Override 3057 public void accept(int result) { 3058 logd("updateSatelliteEntitlementStatus:" + result); 3059 } 3060 }; 3061 } 3062 if (allowedPlmnList == null) { 3063 allowedPlmnList = new ArrayList<>(); 3064 } 3065 if (barredPlmnList == null) { 3066 barredPlmnList = new ArrayList<>(); 3067 } 3068 logd("onSatelliteEntitlementStatusUpdated subId=" + subId + ", entitlementEnabled=" 3069 + entitlementEnabled + ", allowedPlmnList=[" 3070 + String.join(",", allowedPlmnList) + "]" + ", barredPlmnList=[" 3071 + String.join(",", barredPlmnList) + "]"); 3072 3073 synchronized (mSupportedSatelliteServicesLock) { 3074 if (mSatelliteEntitlementStatusPerCarrier.get(subId, false) != entitlementEnabled) { 3075 logd("update the carrier satellite enabled to " + entitlementEnabled); 3076 mSatelliteEntitlementStatusPerCarrier.put(subId, entitlementEnabled); 3077 try { 3078 mSubscriptionManagerService.setSubscriptionProperty(subId, 3079 SATELLITE_ENTITLEMENT_STATUS, entitlementEnabled ? "1" : "0"); 3080 } catch (IllegalArgumentException | SecurityException e) { 3081 loge("onSatelliteEntitlementStatusUpdated: setSubscriptionProperty, e=" + e); 3082 } 3083 } 3084 3085 if (isValidPlmnList(allowedPlmnList) && isValidPlmnList(barredPlmnList)) { 3086 mMergedPlmnListPerCarrier.remove(subId); 3087 mEntitlementPlmnListPerCarrier.put(subId, allowedPlmnList); 3088 mEntitlementBarredPlmnListPerCarrier.put(subId, barredPlmnList); 3089 updatePlmnListPerCarrier(subId); 3090 configureSatellitePlmnForCarrier(subId); 3091 mSubscriptionManagerService.setSatelliteEntitlementPlmnList(subId, allowedPlmnList); 3092 } else { 3093 loge("onSatelliteEntitlementStatusUpdated: either invalid allowedPlmnList " 3094 + "or invalid barredPlmnList"); 3095 } 3096 3097 if (mSatelliteEntitlementStatusPerCarrier.get(subId, false)) { 3098 removeAttachRestrictionForCarrier(subId, 3099 SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT, callback); 3100 } else { 3101 addAttachRestrictionForCarrier(subId, 3102 SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT, callback); 3103 } 3104 } 3105 } 3106 3107 /** 3108 * A list of PLMNs is considered valid if either the list is empty or all PLMNs in the list 3109 * are valid. 3110 */ isValidPlmnList(@onNull List<String> plmnList)3111 private boolean isValidPlmnList(@NonNull List<String> plmnList) { 3112 for (String plmn : plmnList) { 3113 if (!TelephonyUtils.isValidPlmn(plmn)) { 3114 ploge("Invalid PLMN = " + plmn); 3115 return false; 3116 } 3117 } 3118 return true; 3119 } 3120 3121 /** 3122 * If we have not successfully queried the satellite modem for its satellite service support, 3123 * we will retry the query one more time. Otherwise, we will return the cached result. 3124 */ isSatelliteSupportedViaOemInternal()3125 private Boolean isSatelliteSupportedViaOemInternal() { 3126 synchronized (mIsSatelliteSupportedLock) { 3127 if (mIsSatelliteSupported != null) { 3128 /* We have already successfully queried the satellite modem. */ 3129 return mIsSatelliteSupported; 3130 } 3131 } 3132 /** 3133 * We have not successfully checked whether the modem supports satellite service. 3134 * Thus, we need to retry it now. 3135 */ 3136 requestIsSatelliteSupported(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, 3137 new ResultReceiver(this) { 3138 @Override 3139 protected void onReceiveResult(int resultCode, Bundle resultData) { 3140 plogd("isSatelliteSupportedViaOemInternal.requestIsSatelliteSupported:" 3141 + " resultCode=" + resultCode); 3142 } 3143 }); 3144 return null; 3145 } 3146 handleEventProvisionSatelliteServiceDone( @onNull ProvisionSatelliteServiceArgument arg, @SatelliteManager.SatelliteResult int result)3147 private void handleEventProvisionSatelliteServiceDone( 3148 @NonNull ProvisionSatelliteServiceArgument arg, 3149 @SatelliteManager.SatelliteResult int result) { 3150 plogd("handleEventProvisionSatelliteServiceDone: result=" 3151 + result + ", subId=" + arg.subId); 3152 3153 Consumer<Integer> callback = mSatelliteProvisionCallbacks.remove(arg.subId); 3154 if (callback == null) { 3155 ploge("handleEventProvisionSatelliteServiceDone: callback is null for subId=" 3156 + arg.subId); 3157 mProvisionMetricsStats 3158 .setResultCode(SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE) 3159 .setIsProvisionRequest(true) 3160 .reportProvisionMetrics(); 3161 mControllerMetricsStats.reportProvisionCount( 3162 SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE); 3163 return; 3164 } 3165 if (result == SATELLITE_RESULT_SUCCESS 3166 || result == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) { 3167 persistOemEnabledSatelliteProvisionStatus(true); 3168 synchronized (mSatelliteViaOemProvisionLock) { 3169 mIsSatelliteViaOemProvisioned = true; 3170 } 3171 callback.accept(SATELLITE_RESULT_SUCCESS); 3172 handleEventSatelliteProvisionStateChanged(true); 3173 } else { 3174 callback.accept(result); 3175 } 3176 mProvisionMetricsStats.setResultCode(result) 3177 .setIsProvisionRequest(true) 3178 .reportProvisionMetrics(); 3179 mControllerMetricsStats.reportProvisionCount(result); 3180 } 3181 handleEventDeprovisionSatelliteServiceDone( @onNull ProvisionSatelliteServiceArgument arg, @SatelliteManager.SatelliteResult int result)3182 private void handleEventDeprovisionSatelliteServiceDone( 3183 @NonNull ProvisionSatelliteServiceArgument arg, 3184 @SatelliteManager.SatelliteResult int result) { 3185 if (arg == null) { 3186 ploge("handleEventDeprovisionSatelliteServiceDone: arg is null"); 3187 return; 3188 } 3189 plogd("handleEventDeprovisionSatelliteServiceDone: result=" 3190 + result + ", subId=" + arg.subId); 3191 3192 if (result == SATELLITE_RESULT_SUCCESS 3193 || result == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) { 3194 persistOemEnabledSatelliteProvisionStatus(false); 3195 synchronized (mSatelliteViaOemProvisionLock) { 3196 mIsSatelliteViaOemProvisioned = false; 3197 } 3198 if (arg.callback != null) { 3199 arg.callback.accept(SATELLITE_RESULT_SUCCESS); 3200 } 3201 handleEventSatelliteProvisionStateChanged(false); 3202 } else if (arg.callback != null) { 3203 arg.callback.accept(result); 3204 } 3205 mProvisionMetricsStats.setResultCode(result) 3206 .setIsProvisionRequest(false) 3207 .reportProvisionMetrics(); 3208 mControllerMetricsStats.reportDeprovisionCount(result); 3209 } 3210 handleStartSatelliteTransmissionUpdatesDone(@onNull AsyncResult ar)3211 private void handleStartSatelliteTransmissionUpdatesDone(@NonNull AsyncResult ar) { 3212 SatelliteControllerHandlerRequest request = (SatelliteControllerHandlerRequest) ar.userObj; 3213 SatelliteTransmissionUpdateArgument arg = 3214 (SatelliteTransmissionUpdateArgument) request.argument; 3215 int errorCode = SatelliteServiceUtils.getSatelliteError(ar, 3216 "handleStartSatelliteTransmissionUpdatesDone"); 3217 arg.errorCallback.accept(errorCode); 3218 3219 if (errorCode != SATELLITE_RESULT_SUCCESS) { 3220 mPointingAppController.setStartedSatelliteTransmissionUpdates(false); 3221 // We need to remove the callback from our listener list since the caller might not call 3222 // stopSatelliteTransmissionUpdates to unregister the callback in case of failure. 3223 mPointingAppController.unregisterForSatelliteTransmissionUpdates(arg.subId, 3224 arg.errorCallback, arg.callback); 3225 } else { 3226 mPointingAppController.setStartedSatelliteTransmissionUpdates(true); 3227 } 3228 } 3229 3230 /** 3231 * Posts the specified command to be executed on the main thread and returns immediately. 3232 * 3233 * @param command command to be executed on the main thread 3234 * @param argument additional parameters required to perform of the operation 3235 * @param phone phone object used to perform the operation. 3236 */ sendRequestAsync(int command, @NonNull Object argument, @Nullable Phone phone)3237 private void sendRequestAsync(int command, @NonNull Object argument, @Nullable Phone phone) { 3238 SatelliteControllerHandlerRequest request = new SatelliteControllerHandlerRequest( 3239 argument, phone); 3240 Message msg = this.obtainMessage(command, request); 3241 msg.sendToTarget(); 3242 } 3243 3244 /** 3245 * Posts the specified command to be executed on the main thread. As this is a synchronous 3246 * request, it waits until the request is complete and then return the result. 3247 * 3248 * @param command command to be executed on the main thread 3249 * @param argument additional parameters required to perform of the operation 3250 * @param phone phone object used to perform the operation. 3251 * @return result of the operation 3252 */ sendRequest(int command, @NonNull Object argument, @Nullable Phone phone)3253 private @Nullable Object sendRequest(int command, @NonNull Object argument, 3254 @Nullable Phone phone) { 3255 if (Looper.myLooper() == this.getLooper()) { 3256 throw new RuntimeException("This method will deadlock if called from the main thread"); 3257 } 3258 3259 SatelliteControllerHandlerRequest request = new SatelliteControllerHandlerRequest( 3260 argument, phone); 3261 Message msg = this.obtainMessage(command, request); 3262 msg.sendToTarget(); 3263 3264 synchronized (request) { 3265 while(request.result == null) { 3266 try { 3267 request.wait(); 3268 } catch (InterruptedException e) { 3269 // Do nothing, go back and wait until the request is complete. 3270 } 3271 } 3272 } 3273 return request.result; 3274 } 3275 3276 /** 3277 * Check if satellite is provisioned for a subscription on the device. 3278 * @return true if satellite is provisioned on the given subscription else return false. 3279 */ 3280 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) 3281 @Nullable isSatelliteViaOemProvisioned()3282 protected Boolean isSatelliteViaOemProvisioned() { 3283 synchronized (mSatelliteViaOemProvisionLock) { 3284 if (mOverriddenIsSatelliteViaOemProvisioned != null) { 3285 return mOverriddenIsSatelliteViaOemProvisioned; 3286 } 3287 3288 if (mIsSatelliteViaOemProvisioned != null) { 3289 return mIsSatelliteViaOemProvisioned; 3290 } 3291 } 3292 3293 requestIsSatelliteProvisioned(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, 3294 new ResultReceiver(this) { 3295 @Override 3296 protected void onReceiveResult(int resultCode, Bundle resultData) { 3297 plogd("isSatelliteViaOemProvisioned: resultCode=" + resultCode); 3298 } 3299 }); 3300 return null; 3301 } 3302 handleSatelliteEnabled(SatelliteControllerHandlerRequest request)3303 private void handleSatelliteEnabled(SatelliteControllerHandlerRequest request) { 3304 RequestSatelliteEnabledArgument argument = 3305 (RequestSatelliteEnabledArgument) request.argument; 3306 handlePersistentLoggingOnSessionStart(argument); 3307 if (mSatelliteSessionController != null) { 3308 mSatelliteSessionController.onSatelliteEnablementStarted(argument.enableSatellite); 3309 } else { 3310 ploge("handleSatelliteEnabled: mSatelliteSessionController is not initialized yet"); 3311 } 3312 3313 if (!argument.enableSatellite && mSatelliteModemInterface.isSatelliteServiceSupported()) { 3314 synchronized (mIsSatelliteEnabledLock) { 3315 mWaitingForDisableSatelliteModemResponse = true; 3316 mWaitingForSatelliteModemOff = true; 3317 } 3318 } 3319 3320 Message onCompleted = obtainMessage(EVENT_SET_SATELLITE_ENABLED_DONE, request); 3321 mSatelliteModemInterface.requestSatelliteEnabled(argument.enableSatellite, 3322 argument.enableDemoMode, argument.isEmergency, onCompleted); 3323 startWaitForSatelliteEnablingResponseTimer(argument); 3324 // Logs satellite session timestamps for session metrics 3325 if (argument.enableSatellite) { 3326 mSessionStartTimeStamp = System.currentTimeMillis(); 3327 } 3328 mSessionProcessingTimeStamp = System.currentTimeMillis(); 3329 } 3330 handleRequestSatelliteAttachRestrictionForCarrierCmd( SatelliteControllerHandlerRequest request)3331 private void handleRequestSatelliteAttachRestrictionForCarrierCmd( 3332 SatelliteControllerHandlerRequest request) { 3333 RequestHandleSatelliteAttachRestrictionForCarrierArgument argument = 3334 (RequestHandleSatelliteAttachRestrictionForCarrierArgument) request.argument; 3335 3336 if (argument.reason == SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER) { 3337 if (!persistSatelliteAttachEnabledForCarrierSetting(argument.subId)) { 3338 argument.callback.accept(SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE); 3339 return; 3340 } 3341 } 3342 3343 evaluateEnablingSatelliteForCarrier(argument.subId, argument.reason, argument.callback); 3344 } 3345 updateSatelliteSupportedStateWhenSatelliteServiceConnected(boolean supported)3346 private void updateSatelliteSupportedStateWhenSatelliteServiceConnected(boolean supported) { 3347 synchronized (mIsSatelliteSupportedLock) { 3348 mIsSatelliteSupported = supported; 3349 } 3350 mSatelliteSessionController = SatelliteSessionController.make( 3351 mContext, getLooper(), mFeatureFlags, supported); 3352 plogd("create a new SatelliteSessionController due to isSatelliteSupported state has " 3353 + "changed to " + supported); 3354 3355 if (supported) { 3356 registerForSatelliteProvisionStateChanged(); 3357 registerForPendingDatagramCount(); 3358 registerForSatelliteModemStateChanged(); 3359 registerForNtnSignalStrengthChanged(); 3360 registerForCapabilitiesChanged(); 3361 3362 requestIsSatelliteProvisioned(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, 3363 new ResultReceiver(this) { 3364 @Override 3365 protected void onReceiveResult(int resultCode, Bundle resultData) { 3366 plogd("requestIsSatelliteProvisioned: resultCode=" + resultCode 3367 + ", resultData=" + resultData); 3368 requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, 3369 false, false, false, 3370 new IIntegerConsumer.Stub() { 3371 @Override 3372 public void accept(int result) { 3373 plogd("requestSatelliteEnabled: result=" + result); 3374 } 3375 }); 3376 } 3377 }); 3378 requestSatelliteCapabilities(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, 3379 new ResultReceiver(this) { 3380 @Override 3381 protected void onReceiveResult(int resultCode, Bundle resultData) { 3382 plogd("requestSatelliteCapabilities: resultCode=" + resultCode 3383 + ", resultData=" + resultData); 3384 } 3385 }); 3386 } 3387 registerForSatelliteSupportedStateChanged(); 3388 } 3389 updateSatelliteEnabledState(boolean enabled, String caller)3390 private void updateSatelliteEnabledState(boolean enabled, String caller) { 3391 synchronized (mIsSatelliteEnabledLock) { 3392 mIsSatelliteEnabled = enabled; 3393 } 3394 if (mSatelliteSessionController != null) { 3395 mSatelliteSessionController.onSatelliteEnabledStateChanged(enabled); 3396 mSatelliteSessionController.setDemoMode(mIsDemoModeEnabled); 3397 } else { 3398 ploge(caller + ": mSatelliteSessionController is not initialized yet"); 3399 } 3400 if (!enabled) { 3401 mIsModemEnabledReportingNtnSignalStrength.set(false); 3402 } 3403 } 3404 registerForSatelliteProvisionStateChanged()3405 private void registerForSatelliteProvisionStateChanged() { 3406 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 3407 if (!mRegisteredForProvisionStateChangedWithSatelliteService.get()) { 3408 mSatelliteModemInterface.registerForSatelliteProvisionStateChanged( 3409 this, EVENT_SATELLITE_PROVISION_STATE_CHANGED, null); 3410 mRegisteredForProvisionStateChangedWithSatelliteService.set(true); 3411 } 3412 } 3413 } 3414 registerForPendingDatagramCount()3415 private void registerForPendingDatagramCount() { 3416 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 3417 if (!mRegisteredForPendingDatagramCountWithSatelliteService.get()) { 3418 mSatelliteModemInterface.registerForPendingDatagrams( 3419 this, EVENT_PENDING_DATAGRAMS, null); 3420 mRegisteredForPendingDatagramCountWithSatelliteService.set(true); 3421 } 3422 } 3423 } 3424 registerForSatelliteModemStateChanged()3425 private void registerForSatelliteModemStateChanged() { 3426 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 3427 if (!mRegisteredForSatelliteModemStateChangedWithSatelliteService.get()) { 3428 mSatelliteModemInterface.registerForSatelliteModemStateChanged( 3429 this, EVENT_SATELLITE_MODEM_STATE_CHANGED, null); 3430 mRegisteredForSatelliteModemStateChangedWithSatelliteService.set(true); 3431 } 3432 } 3433 } 3434 registerForNtnSignalStrengthChanged()3435 private void registerForNtnSignalStrengthChanged() { 3436 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 3437 plogd("registerForNtnSignalStrengthChanged: oemEnabledSatelliteFlag is disabled"); 3438 return; 3439 } 3440 3441 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 3442 if (!mRegisteredForNtnSignalStrengthChanged.get()) { 3443 mSatelliteModemInterface.registerForNtnSignalStrengthChanged( 3444 this, EVENT_NTN_SIGNAL_STRENGTH_CHANGED, null); 3445 mRegisteredForNtnSignalStrengthChanged.set(true); 3446 } 3447 } 3448 } 3449 registerForCapabilitiesChanged()3450 private void registerForCapabilitiesChanged() { 3451 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 3452 plogd("registerForCapabilitiesChanged: oemEnabledSatelliteFlag is disabled"); 3453 return; 3454 } 3455 3456 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 3457 if (!mRegisteredForSatelliteCapabilitiesChanged.get()) { 3458 mSatelliteModemInterface.registerForSatelliteCapabilitiesChanged( 3459 this, EVENT_SATELLITE_CAPABILITIES_CHANGED, null); 3460 mRegisteredForSatelliteCapabilitiesChanged.set(true); 3461 } 3462 } 3463 } 3464 registerForSatelliteSupportedStateChanged()3465 private void registerForSatelliteSupportedStateChanged() { 3466 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 3467 if (!mRegisteredForSatelliteSupportedStateChanged.get()) { 3468 mSatelliteModemInterface.registerForSatelliteSupportedStateChanged( 3469 this, EVENT_SATELLITE_SUPPORTED_STATE_CHANGED, null); 3470 mRegisteredForSatelliteSupportedStateChanged.set(true); 3471 } 3472 } 3473 } 3474 handleEventSatelliteProvisionStateChanged(boolean provisioned)3475 private void handleEventSatelliteProvisionStateChanged(boolean provisioned) { 3476 plogd("handleSatelliteProvisionStateChangedEvent: provisioned=" + provisioned); 3477 3478 synchronized (mSatelliteViaOemProvisionLock) { 3479 persistOemEnabledSatelliteProvisionStatus(provisioned); 3480 mIsSatelliteViaOemProvisioned = provisioned; 3481 } 3482 3483 List<ISatelliteProvisionStateCallback> deadCallersList = new ArrayList<>(); 3484 mSatelliteProvisionStateChangedListeners.values().forEach(listener -> { 3485 try { 3486 listener.onSatelliteProvisionStateChanged(provisioned); 3487 } catch (RemoteException e) { 3488 plogd("handleSatelliteProvisionStateChangedEvent RemoteException: " + e); 3489 deadCallersList.add(listener); 3490 } 3491 }); 3492 deadCallersList.forEach(listener -> { 3493 mSatelliteProvisionStateChangedListeners.remove(listener.asBinder()); 3494 }); 3495 } 3496 handleEventSatelliteModemStateChanged( @atelliteManager.SatelliteModemState int state)3497 private void handleEventSatelliteModemStateChanged( 3498 @SatelliteManager.SatelliteModemState int state) { 3499 plogd("handleEventSatelliteModemStateChanged: state=" + state); 3500 if (state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE 3501 || state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) { 3502 synchronized (mIsSatelliteEnabledLock) { 3503 if ((state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE) 3504 || ((mIsSatelliteEnabled == null || isSatelliteEnabled()) 3505 && !mWaitingForDisableSatelliteModemResponse)) { 3506 int error = (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) 3507 ? SATELLITE_RESULT_SUCCESS 3508 : SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE; 3509 Consumer<Integer> callback = null; 3510 synchronized (mSatelliteEnabledRequestLock) { 3511 if (mSatelliteEnabledRequest != null) { 3512 callback = mSatelliteEnabledRequest.callback; 3513 } 3514 } 3515 moveSatelliteToOffStateAndCleanUpResources(error, callback); 3516 } else { 3517 plogd("Either waiting for the response of disabling satellite modem or the" 3518 + " event should be ignored because isSatelliteEnabled=" 3519 + isSatelliteEnabled() 3520 + ", mIsSatelliteEnabled=" + mIsSatelliteEnabled); 3521 } 3522 mWaitingForSatelliteModemOff = false; 3523 } 3524 } else { 3525 if (mSatelliteSessionController != null) { 3526 mSatelliteSessionController.onSatelliteModemStateChanged(state); 3527 } else { 3528 ploge("handleEventSatelliteModemStateChanged: mSatelliteSessionController is null"); 3529 } 3530 } 3531 } 3532 handleEventNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength)3533 private void handleEventNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) { 3534 logd("handleEventNtnSignalStrengthChanged: ntnSignalStrength=" + ntnSignalStrength); 3535 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 3536 logd("handleEventNtnSignalStrengthChanged: oemEnabledSatelliteFlag is disabled"); 3537 return; 3538 } 3539 3540 synchronized (mNtnSignalsStrengthLock) { 3541 mNtnSignalStrength = ntnSignalStrength; 3542 } 3543 mSessionMetricsStats.updateMaxNtnSignalStrengthLevel(ntnSignalStrength.getLevel()); 3544 3545 List<INtnSignalStrengthCallback> deadCallersList = new ArrayList<>(); 3546 mNtnSignalStrengthChangedListeners.values().forEach(listener -> { 3547 try { 3548 listener.onNtnSignalStrengthChanged(ntnSignalStrength); 3549 } catch (RemoteException e) { 3550 plogd("handleEventNtnSignalStrengthChanged RemoteException: " + e); 3551 deadCallersList.add(listener); 3552 } 3553 }); 3554 deadCallersList.forEach(listener -> { 3555 mNtnSignalStrengthChangedListeners.remove(listener.asBinder()); 3556 }); 3557 } 3558 handleEventSatelliteCapabilitiesChanged(SatelliteCapabilities capabilities)3559 private void handleEventSatelliteCapabilitiesChanged(SatelliteCapabilities capabilities) { 3560 plogd("handleEventSatelliteCapabilitiesChanged()"); 3561 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 3562 plogd("handleEventSatelliteCapabilitiesChanged: oemEnabledSatelliteFlag is disabled"); 3563 return; 3564 } 3565 3566 synchronized (mSatelliteCapabilitiesLock) { 3567 mSatelliteCapabilities = capabilities; 3568 } 3569 3570 List<ISatelliteCapabilitiesCallback> deadCallersList = new ArrayList<>(); 3571 mSatelliteCapabilitiesChangedListeners.values().forEach(listener -> { 3572 try { 3573 listener.onSatelliteCapabilitiesChanged(capabilities); 3574 } catch (RemoteException e) { 3575 plogd("handleEventSatelliteCapabilitiesChanged RemoteException: " + e); 3576 deadCallersList.add(listener); 3577 } 3578 }); 3579 deadCallersList.forEach(listener -> { 3580 mSatelliteCapabilitiesChangedListeners.remove(listener.asBinder()); 3581 }); 3582 } 3583 handleEventSatelliteSupportedStateChanged(boolean supported)3584 private void handleEventSatelliteSupportedStateChanged(boolean supported) { 3585 plogd("handleSatelliteSupportedStateChangedEvent: supported=" + supported); 3586 3587 synchronized (mIsSatelliteSupportedLock) { 3588 if (mIsSatelliteSupported != null && mIsSatelliteSupported == supported) { 3589 if (DBG) { 3590 plogd("current satellite support state and new supported state are matched," 3591 + " ignore update."); 3592 } 3593 return; 3594 } 3595 3596 updateSatelliteSupportedStateWhenSatelliteServiceConnected(supported); 3597 3598 /* In case satellite has been reported as not support from modem, but satellite is 3599 enabled, request disable satellite. */ 3600 synchronized (mIsSatelliteEnabledLock) { 3601 if (!supported && mIsSatelliteEnabled != null && mIsSatelliteEnabled) { 3602 plogd("Invoke requestSatelliteEnabled(), supported=false, " 3603 + "mIsSatelliteEnabled=true"); 3604 requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, 3605 false /* enableSatellite */, false /* enableDemoMode */, 3606 false /* isEmergency */, 3607 new IIntegerConsumer.Stub() { 3608 @Override 3609 public void accept(int result) { 3610 plogd("handleSatelliteSupportedStateChangedEvent: request " 3611 + "satellite disable, result=" 3612 + result); 3613 } 3614 }); 3615 3616 } 3617 } 3618 mIsSatelliteSupported = supported; 3619 } 3620 3621 List<ISatelliteSupportedStateCallback> deadCallersList = new ArrayList<>(); 3622 mSatelliteSupportedStateChangedListeners.values().forEach(listener -> { 3623 try { 3624 listener.onSatelliteSupportedStateChanged(supported); 3625 } catch (RemoteException e) { 3626 plogd("handleSatelliteSupportedStateChangedEvent RemoteException: " + e); 3627 deadCallersList.add(listener); 3628 } 3629 }); 3630 deadCallersList.forEach(listener -> { 3631 mSatelliteSupportedStateChangedListeners.remove(listener.asBinder()); 3632 }); 3633 } 3634 3635 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) setSettingsKeyForSatelliteMode(int val)3636 protected void setSettingsKeyForSatelliteMode(int val) { 3637 plogd("setSettingsKeyForSatelliteMode val: " + val); 3638 Settings.Global.putInt(mContext.getContentResolver(), 3639 Settings.Global.SATELLITE_MODE_ENABLED, val); 3640 } 3641 3642 /** 3643 * Allow screen rotation temporary in rotation locked foldable device. 3644 * <p> 3645 * Temporarily allow screen rotation user to catch satellite signals properly by UI guide in 3646 * emergency situations. Unlock the setting value so that the screen rotation is not locked, and 3647 * return it to the original value when the satellite service is finished. 3648 * <p> 3649 * Note that, only the unfolded screen will be temporarily allowed screen rotation. 3650 * 3651 * @param val {@link SATELLITE_MODE_ENABLED_TRUE} if satellite mode is enabled, 3652 * {@link SATELLITE_MODE_ENABLED_FALSE} satellite mode is not enabled. 3653 */ 3654 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) setSettingsKeyToAllowDeviceRotation(int val)3655 protected void setSettingsKeyToAllowDeviceRotation(int val) { 3656 // Only allows on a foldable device type. 3657 if (!isFoldable(mContext)) { 3658 return; 3659 } 3660 3661 switch (val) { 3662 case SATELLITE_MODE_ENABLED_TRUE: 3663 mDeviceRotationLockToBackupAndRestore = 3664 Settings.Secure.getString(mContentResolver, 3665 Settings.Secure.DEVICE_STATE_ROTATION_LOCK); 3666 String unlockedRotationSettings = replaceDeviceRotationValue( 3667 mDeviceRotationLockToBackupAndRestore == null 3668 ? "" : mDeviceRotationLockToBackupAndRestore, 3669 Settings.Secure.DEVICE_STATE_ROTATION_KEY_UNFOLDED, 3670 Settings.Secure.DEVICE_STATE_ROTATION_LOCK_UNLOCKED); 3671 Settings.Secure.putString(mContentResolver, 3672 Settings.Secure.DEVICE_STATE_ROTATION_LOCK, unlockedRotationSettings); 3673 logd("setSettingsKeyToAllowDeviceRotation(TRUE), RotationSettings is changed" 3674 + " from " + mDeviceRotationLockToBackupAndRestore 3675 + " to " + unlockedRotationSettings); 3676 break; 3677 case SATELLITE_MODE_ENABLED_FALSE: 3678 if (mDeviceRotationLockToBackupAndRestore == null) { 3679 break; 3680 } 3681 Settings.Secure.putString(mContentResolver, 3682 Settings.Secure.DEVICE_STATE_ROTATION_LOCK, 3683 mDeviceRotationLockToBackupAndRestore); 3684 logd("setSettingsKeyToAllowDeviceRotation(FALSE), RotationSettings is restored to" 3685 + mDeviceRotationLockToBackupAndRestore); 3686 mDeviceRotationLockToBackupAndRestore = ""; 3687 break; 3688 default: 3689 loge("setSettingsKeyToAllowDeviceRotation(" + val + "), never reach here."); 3690 break; 3691 } 3692 } 3693 3694 /** 3695 * If the device type is foldable. 3696 * 3697 * @param context context 3698 * @return {@code true} if device type is foldable. {@code false} for otherwise. 3699 */ isFoldable(Context context)3700 private boolean isFoldable(Context context) { 3701 return context.getResources().getIntArray(R.array.config_foldedDeviceStates).length > 0; 3702 } 3703 3704 /** 3705 * Replaces a value of given a target key with a new value in a string of key-value pairs. 3706 * <p> 3707 * Replaces the value corresponding to the target key with a new value. If the key value is not 3708 * found in the device rotation information, it is not replaced. 3709 * 3710 * @param deviceRotationValue Device rotation key values separated by colon(':'). 3711 * @param targetKey The key of the new item caller wants to add. 3712 * @param newValue The value of the new item caller want to add. 3713 * @return A new string where all the key-value pairs. 3714 */ replaceDeviceRotationValue( @onNull String deviceRotationValue, int targetKey, int newValue)3715 private static String replaceDeviceRotationValue( 3716 @NonNull String deviceRotationValue, int targetKey, int newValue) { 3717 // Use list of Key-Value pair 3718 List<Pair<Integer, Integer>> keyValuePairs = new ArrayList<>(); 3719 3720 String[] pairs = deviceRotationValue.split(":"); 3721 if (pairs.length % 2 != 0) { 3722 // Return without modifying. The key-value may be incorrect if length is an odd number. 3723 loge("The length of key-value pair do not match. Return without modification."); 3724 return deviceRotationValue; 3725 } 3726 3727 // collect into keyValuePairs 3728 for (int i = 0; i < pairs.length; i += 2) { 3729 try { 3730 int key = Integer.parseInt(pairs[i]); 3731 int value = Integer.parseInt(pairs[i + 1]); 3732 keyValuePairs.add(new Pair<>(key, key == targetKey ? newValue : value)); 3733 } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { 3734 // Return without modifying if got exception. 3735 loge("got error while parsing key-value. Return without modification. e:" + e); 3736 return deviceRotationValue; 3737 } 3738 } 3739 3740 return keyValuePairs.stream() 3741 .map(pair -> pair.first + ":" + pair.second) // Convert to "key:value" format 3742 .collect(Collectors.joining(":")); // Join pairs with colons 3743 } 3744 3745 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) areAllRadiosDisabled()3746 protected boolean areAllRadiosDisabled() { 3747 synchronized (mRadioStateLock) { 3748 if ((mDisableBTOnSatelliteEnabled && mBTStateEnabled) 3749 || (mDisableNFCOnSatelliteEnabled && mNfcStateEnabled) 3750 || (mDisableWifiOnSatelliteEnabled && mWifiStateEnabled) 3751 || (mDisableUWBOnSatelliteEnabled && mUwbStateEnabled)) { 3752 plogd("All radios are not disabled yet."); 3753 return false; 3754 } 3755 plogd("All radios are disabled."); 3756 return true; 3757 } 3758 } 3759 evaluateToSendSatelliteEnabledSuccess()3760 private void evaluateToSendSatelliteEnabledSuccess() { 3761 plogd("evaluateToSendSatelliteEnabledSuccess"); 3762 synchronized (mSatelliteEnabledRequestLock) { 3763 if (areAllRadiosDisabled() && (mSatelliteEnabledRequest != null) 3764 && mWaitingForRadioDisabled) { 3765 plogd("Sending success to callback that sent enable satellite request"); 3766 mIsEmergency = mSatelliteEnabledRequest.isEmergency; 3767 synchronized (mIsSatelliteEnabledLock) { 3768 mIsSatelliteEnabled = mSatelliteEnabledRequest.enableSatellite; 3769 } 3770 mSatelliteEnabledRequest.callback.accept(SATELLITE_RESULT_SUCCESS); 3771 updateSatelliteEnabledState( 3772 mSatelliteEnabledRequest.enableSatellite, 3773 "EVENT_SET_SATELLITE_ENABLED_DONE"); 3774 mSatelliteEnabledRequest = null; 3775 mWaitingForRadioDisabled = false; 3776 } 3777 } 3778 } 3779 resetSatelliteEnabledRequest()3780 private void resetSatelliteEnabledRequest() { 3781 plogd("resetSatelliteEnabledRequest"); 3782 synchronized (mSatelliteEnabledRequestLock) { 3783 mSatelliteEnabledRequest = null; 3784 mWaitingForRadioDisabled = false; 3785 } 3786 } 3787 moveSatelliteToOffStateAndCleanUpResources( @atelliteManager.SatelliteResult int error, @Nullable Consumer<Integer> callback)3788 private void moveSatelliteToOffStateAndCleanUpResources( 3789 @SatelliteManager.SatelliteResult int error, @Nullable Consumer<Integer> callback) { 3790 plogd("moveSatelliteToOffStateAndCleanUpResources"); 3791 synchronized (mIsSatelliteEnabledLock) { 3792 resetSatelliteEnabledRequest(); 3793 setDemoModeEnabled(false); 3794 handlePersistentLoggingOnSessionEnd(mIsEmergency); 3795 mIsEmergency = false; 3796 mIsSatelliteEnabled = false; 3797 setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_FALSE); 3798 setSettingsKeyToAllowDeviceRotation(SATELLITE_MODE_ENABLED_FALSE); 3799 if (callback != null) callback.accept(error); 3800 updateSatelliteEnabledState( 3801 false, "moveSatelliteToOffStateAndCleanUpResources"); 3802 } 3803 } 3804 setDemoModeEnabled(boolean enabled)3805 private void setDemoModeEnabled(boolean enabled) { 3806 mIsDemoModeEnabled = enabled; 3807 mDatagramController.setDemoMode(mIsDemoModeEnabled); 3808 plogd("setDemoModeEnabled: mIsDemoModeEnabled=" + mIsDemoModeEnabled); 3809 } 3810 isMockModemAllowed()3811 private boolean isMockModemAllowed() { 3812 return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false)); 3813 } 3814 configureSatellitePlmnForCarrier(int subId)3815 private void configureSatellitePlmnForCarrier(int subId) { 3816 logd("configureSatellitePlmnForCarrier"); 3817 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 3818 logd("configureSatellitePlmnForCarrier: carrierEnabledSatelliteFlag is disabled"); 3819 return; 3820 } 3821 synchronized (mSupportedSatelliteServicesLock) { 3822 List<String> carrierPlmnList = mMergedPlmnListPerCarrier.get(subId, 3823 new ArrayList<>()).stream().toList(); 3824 List<String> barredPlmnList = mEntitlementBarredPlmnListPerCarrier.get(subId, 3825 new ArrayList<>()).stream().toList(); 3826 int slotId = SubscriptionManager.getSlotIndex(subId); 3827 mSatelliteModemInterface.setSatellitePlmn(slotId, carrierPlmnList, 3828 SatelliteServiceUtils.mergeStrLists( 3829 carrierPlmnList, mSatellitePlmnListFromOverlayConfig, barredPlmnList), 3830 obtainMessage(EVENT_SET_SATELLITE_PLMN_INFO_DONE)); 3831 } 3832 } 3833 handleSetSatellitePlmnInfoDoneEvent(Message msg)3834 private void handleSetSatellitePlmnInfoDoneEvent(Message msg) { 3835 AsyncResult ar = (AsyncResult) msg.obj; 3836 SatelliteServiceUtils.getSatelliteError(ar, "handleSetSatellitePlmnInfoCmd"); 3837 } 3838 updateSupportedSatelliteServicesForActiveSubscriptions()3839 private void updateSupportedSatelliteServicesForActiveSubscriptions() { 3840 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 3841 logd("updateSupportedSatelliteServicesForActiveSubscriptions: " 3842 + "carrierEnabledSatelliteFlag is disabled"); 3843 return; 3844 } 3845 3846 synchronized (mSupportedSatelliteServicesLock) { 3847 mSatelliteServicesSupportedByCarriers.clear(); 3848 mMergedPlmnListPerCarrier.clear(); 3849 int[] activeSubIds = mSubscriptionManagerService.getActiveSubIdList(true); 3850 if (activeSubIds != null) { 3851 for (int subId : activeSubIds) { 3852 updateSupportedSatelliteServices(subId); 3853 } 3854 } else { 3855 loge("updateSupportedSatelliteServicesForActiveSubscriptions: " 3856 + "activeSubIds is null"); 3857 } 3858 } 3859 } 3860 3861 /** 3862 * If the entitlementPlmnList exist then used it. 3863 * Otherwise, If the carrierPlmnList exist then used it. 3864 */ updatePlmnListPerCarrier(int subId)3865 private void updatePlmnListPerCarrier(int subId) { 3866 plogd("updatePlmnListPerCarrier: subId=" + subId); 3867 synchronized (mSupportedSatelliteServicesLock) { 3868 List<String> carrierPlmnList, entitlementPlmnList; 3869 if (getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, 3870 false)) { 3871 entitlementPlmnList = mEntitlementPlmnListPerCarrier.get(subId, 3872 new ArrayList<>()).stream().toList(); 3873 plogd("updatePlmnListPerCarrier: entitlementPlmnList=" 3874 + String.join(",", entitlementPlmnList) 3875 + " size=" + entitlementPlmnList.size()); 3876 if (!entitlementPlmnList.isEmpty()) { 3877 mMergedPlmnListPerCarrier.put(subId, entitlementPlmnList); 3878 plogd("mMergedPlmnListPerCarrier is updated by Entitlement"); 3879 mCarrierRoamingSatelliteControllerStats.reportConfigDataSource( 3880 SatelliteConstants.CONFIG_DATA_SOURCE_ENTITLEMENT); 3881 return; 3882 } 3883 } 3884 3885 SatelliteConfig satelliteConfig = getSatelliteConfig(); 3886 if (satelliteConfig != null) { 3887 TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); 3888 int carrierId = tm.createForSubscriptionId(subId).getSimCarrierId(); 3889 List<String> plmnList = satelliteConfig.getAllSatellitePlmnsForCarrier(carrierId); 3890 if (!plmnList.isEmpty()) { 3891 plogd("mMergedPlmnListPerCarrier is updated by ConfigUpdater : " 3892 + String.join(",", plmnList)); 3893 mMergedPlmnListPerCarrier.put(subId, plmnList); 3894 mCarrierRoamingSatelliteControllerStats.reportConfigDataSource( 3895 SatelliteConstants.CONFIG_DATA_SOURCE_CONFIG_UPDATER); 3896 return; 3897 } 3898 } 3899 3900 if (mSatelliteServicesSupportedByCarriers.containsKey(subId) 3901 && mSatelliteServicesSupportedByCarriers.get(subId) != null) { 3902 carrierPlmnList = 3903 mSatelliteServicesSupportedByCarriers.get(subId).keySet().stream().toList(); 3904 plogd("mMergedPlmnListPerCarrier is updated by carrier config: " 3905 + String.join(",", carrierPlmnList)); 3906 mCarrierRoamingSatelliteControllerStats.reportConfigDataSource( 3907 SatelliteConstants.CONFIG_DATA_SOURCE_CARRIER_CONFIG); 3908 } else { 3909 carrierPlmnList = new ArrayList<>(); 3910 plogd("Empty mMergedPlmnListPerCarrier"); 3911 } 3912 mMergedPlmnListPerCarrier.put(subId, carrierPlmnList); 3913 } 3914 } 3915 updateSupportedSatelliteServices(int subId)3916 private void updateSupportedSatelliteServices(int subId) { 3917 plogd("updateSupportedSatelliteServices with subId " + subId); 3918 synchronized (mSupportedSatelliteServicesLock) { 3919 SatelliteConfig satelliteConfig = getSatelliteConfig(); 3920 3921 TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); 3922 int carrierId = tm.createForSubscriptionId(subId).getSimCarrierId(); 3923 3924 if (satelliteConfig != null) { 3925 Map<String, Set<Integer>> supportedServicesPerPlmn = 3926 satelliteConfig.getSupportedSatelliteServices(carrierId); 3927 if (!supportedServicesPerPlmn.isEmpty()) { 3928 mSatelliteServicesSupportedByCarriers.put(subId, supportedServicesPerPlmn); 3929 plogd("updateSupportedSatelliteServices using ConfigUpdater, " 3930 + "supportedServicesPerPlmn = " + supportedServicesPerPlmn.size()); 3931 updatePlmnListPerCarrier(subId); 3932 return; 3933 } else { 3934 plogd("supportedServicesPerPlmn is empty"); 3935 } 3936 } 3937 3938 mSatelliteServicesSupportedByCarriers.put( 3939 subId, readSupportedSatelliteServicesFromCarrierConfig(subId)); 3940 updatePlmnListPerCarrier(subId); 3941 plogd("updateSupportedSatelliteServices using carrier config"); 3942 } 3943 } 3944 3945 @NonNull readSatellitePlmnsFromOverlayConfig()3946 private List<String> readSatellitePlmnsFromOverlayConfig() { 3947 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 3948 logd("readSatellitePlmnsFromOverlayConfig: carrierEnabledSatelliteFlag is disabled"); 3949 return new ArrayList<>(); 3950 } 3951 3952 String[] devicePlmns = readStringArrayFromOverlayConfig( 3953 R.array.config_satellite_providers); 3954 return Arrays.stream(devicePlmns).toList(); 3955 } 3956 3957 @NonNull readSupportedSatelliteServicesFromCarrierConfig(int subId)3958 private Map<String, Set<Integer>> readSupportedSatelliteServicesFromCarrierConfig(int subId) { 3959 PersistableBundle config = getPersistableBundle(subId); 3960 return SatelliteServiceUtils.parseSupportedSatelliteServices( 3961 config.getPersistableBundle( 3962 KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE)); 3963 } 3964 getConfigForSubId(int subId)3965 @NonNull private PersistableBundle getConfigForSubId(int subId) { 3966 PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId, 3967 KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE, 3968 KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, 3969 KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT, 3970 KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, 3971 KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY, 3972 KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL, 3973 KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT); 3974 if (config == null || config.isEmpty()) { 3975 config = CarrierConfigManager.getDefaultConfig(); 3976 } 3977 return config; 3978 } 3979 handleCarrierConfigChanged(int slotIndex, int subId, int carrierId, int specificCarrierId)3980 private void handleCarrierConfigChanged(int slotIndex, int subId, int carrierId, 3981 int specificCarrierId) { 3982 plogd("handleCarrierConfigChanged(): slotIndex(" + slotIndex + "), subId(" 3983 + subId + "), carrierId(" + carrierId + "), specificCarrierId(" 3984 + specificCarrierId + ")"); 3985 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 3986 return; 3987 } 3988 3989 updateCarrierConfig(subId); 3990 updateEntitlementPlmnListPerCarrier(subId); 3991 updateSupportedSatelliteServicesForActiveSubscriptions(); 3992 processNewCarrierConfigData(subId); 3993 resetCarrierRoamingSatelliteModeParams(subId); 3994 } 3995 processNewCarrierConfigData(int subId)3996 private void processNewCarrierConfigData(int subId) { 3997 configureSatellitePlmnForCarrier(subId); 3998 setSatelliteAttachEnabledForCarrierOnSimLoaded(subId); 3999 updateRestrictReasonForEntitlementPerCarrier(subId); 4000 } 4001 4002 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) updateCarrierConfig(int subId)4003 protected void updateCarrierConfig(int subId) { 4004 synchronized (mCarrierConfigArrayLock) { 4005 mCarrierConfigArray.put(subId, getConfigForSubId(subId)); 4006 } 4007 } 4008 4009 /** 4010 * If there is no cached entitlement plmn list, read it from the db and use it if it is not an 4011 * empty list. 4012 */ updateEntitlementPlmnListPerCarrier(int subId)4013 private void updateEntitlementPlmnListPerCarrier(int subId) { 4014 if (!getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false)) { 4015 plogd("don't support entitlement"); 4016 return; 4017 } 4018 4019 synchronized (mSupportedSatelliteServicesLock) { 4020 if (mEntitlementPlmnListPerCarrier.indexOfKey(subId) < 0) { 4021 plogd("updateEntitlementPlmnListPerCarrier: no correspondent cache, load from " 4022 + "persist storage"); 4023 List<String> entitlementPlmnList = 4024 mSubscriptionManagerService.getSatelliteEntitlementPlmnList(subId); 4025 if (entitlementPlmnList.isEmpty()) { 4026 plogd("updateEntitlementPlmnListPerCarrier: read empty list"); 4027 return; 4028 } 4029 plogd("updateEntitlementPlmnListPerCarrier: entitlementPlmnList=" 4030 + String.join(",", entitlementPlmnList)); 4031 mEntitlementPlmnListPerCarrier.put(subId, entitlementPlmnList); 4032 } 4033 } 4034 } 4035 4036 /** 4037 * When a SIM is loaded, we need to check if users has enabled satellite attach for the carrier 4038 * associated with the SIM, and evaluate if satellite should be enabled for the carrier. 4039 * 4040 * @param subId Subscription ID. 4041 */ setSatelliteAttachEnabledForCarrierOnSimLoaded(int subId)4042 private void setSatelliteAttachEnabledForCarrierOnSimLoaded(int subId) { 4043 synchronized (mIsSatelliteEnabledLock) { 4044 if (isSatelliteAttachEnabledForCarrierByUser(subId) 4045 && !mIsSatelliteAttachEnabledForCarrierArrayPerSub.getOrDefault(subId, 4046 false)) { 4047 evaluateEnablingSatelliteForCarrier(subId, 4048 SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, null); 4049 } 4050 } 4051 } 4052 4053 @NonNull readStringArrayFromOverlayConfig(@rrayRes int id)4054 private String[] readStringArrayFromOverlayConfig(@ArrayRes int id) { 4055 String[] strArray = null; 4056 try { 4057 strArray = mContext.getResources().getStringArray(id); 4058 } catch (Resources.NotFoundException ex) { 4059 ploge("readStringArrayFromOverlayConfig: id= " + id + ", ex=" + ex); 4060 } 4061 if (strArray == null) { 4062 strArray = new String[0]; 4063 } 4064 return strArray; 4065 } 4066 isSatelliteSupportedViaCarrier(int subId)4067 private boolean isSatelliteSupportedViaCarrier(int subId) { 4068 return getConfigForSubId(subId) 4069 .getBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL); 4070 } 4071 4072 /** 4073 * Check if satellite attach is enabled by user for the carrier associated with the 4074 * {@code subId}. 4075 * 4076 * @param subId Subscription ID. 4077 * 4078 * @return Returns {@code true} if satellite attach for carrier is enabled by user, 4079 * {@code false} otherwise. 4080 */ isSatelliteAttachEnabledForCarrierByUser(int subId)4081 private boolean isSatelliteAttachEnabledForCarrierByUser(int subId) { 4082 synchronized (mIsSatelliteEnabledLock) { 4083 Set<Integer> cachedRestrictionSet = 4084 mSatelliteAttachRestrictionForCarrierArray.get(subId); 4085 if (cachedRestrictionSet != null) { 4086 return !cachedRestrictionSet.contains( 4087 SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER); 4088 } else { 4089 plogd("isSatelliteAttachEnabledForCarrierByUser() no correspondent cache, " 4090 + "load from persist storage"); 4091 try { 4092 String enabled = 4093 mSubscriptionManagerService.getSubscriptionProperty(subId, 4094 SATELLITE_ATTACH_ENABLED_FOR_CARRIER, 4095 mContext.getOpPackageName(), mContext.getAttributionTag()); 4096 4097 if (enabled == null) { 4098 ploge("isSatelliteAttachEnabledForCarrierByUser: invalid subId, subId=" 4099 + subId); 4100 return false; 4101 } 4102 4103 if (enabled.isEmpty()) { 4104 ploge("isSatelliteAttachEnabledForCarrierByUser: no data for subId(" + subId 4105 + ")"); 4106 return false; 4107 } 4108 4109 synchronized (mIsSatelliteEnabledLock) { 4110 boolean result = enabled.equals("1"); 4111 if (!result) { 4112 mSatelliteAttachRestrictionForCarrierArray.put(subId, new HashSet<>()); 4113 mSatelliteAttachRestrictionForCarrierArray.get(subId).add( 4114 SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER); 4115 } 4116 return result; 4117 } 4118 } catch (IllegalArgumentException | SecurityException ex) { 4119 ploge("isSatelliteAttachEnabledForCarrierByUser: ex=" + ex); 4120 return false; 4121 } 4122 } 4123 } 4124 } 4125 4126 /** 4127 * Check whether there is any reason to restrict satellite communication for the carrier 4128 * associated with the {@code subId}. 4129 * 4130 * @param subId Subscription ID 4131 * @return {@code true} when there is at least on reason, {@code false} otherwise. 4132 */ hasReasonToRestrictSatelliteCommunicationForCarrier(int subId)4133 private boolean hasReasonToRestrictSatelliteCommunicationForCarrier(int subId) { 4134 synchronized (mIsSatelliteEnabledLock) { 4135 return !mSatelliteAttachRestrictionForCarrierArray 4136 .getOrDefault(subId, Collections.emptySet()).isEmpty(); 4137 } 4138 } 4139 updateRestrictReasonForEntitlementPerCarrier(int subId)4140 private void updateRestrictReasonForEntitlementPerCarrier(int subId) { 4141 if (!getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false)) { 4142 plogd("don't support entitlement"); 4143 return; 4144 } 4145 4146 IIntegerConsumer callback = new IIntegerConsumer.Stub() { 4147 @Override 4148 public void accept(int result) { 4149 plogd("updateRestrictReasonForEntitlementPerCarrier:" + result); 4150 } 4151 }; 4152 synchronized (mSupportedSatelliteServicesLock) { 4153 if (mSatelliteEntitlementStatusPerCarrier.indexOfKey(subId) < 0) { 4154 plogd("updateRestrictReasonForEntitlementPerCarrier: no correspondent cache, " 4155 + "load from persist storage"); 4156 String entitlementStatus = null; 4157 try { 4158 entitlementStatus = 4159 mSubscriptionManagerService.getSubscriptionProperty(subId, 4160 SATELLITE_ENTITLEMENT_STATUS, mContext.getOpPackageName(), 4161 mContext.getAttributionTag()); 4162 } catch (IllegalArgumentException | SecurityException e) { 4163 ploge("updateRestrictReasonForEntitlementPerCarrier, e=" + e); 4164 } 4165 4166 if (entitlementStatus == null) { 4167 ploge("updateRestrictReasonForEntitlementPerCarrier: invalid subId, subId=" 4168 + subId + " set to default value"); 4169 entitlementStatus = "0"; 4170 } 4171 4172 if (entitlementStatus.isEmpty()) { 4173 ploge("updateRestrictReasonForEntitlementPerCarrier: no data for subId(" + subId 4174 + "). set to default value"); 4175 entitlementStatus = "0"; 4176 } 4177 boolean result = entitlementStatus.equals("1"); 4178 mSatelliteEntitlementStatusPerCarrier.put(subId, result); 4179 } 4180 4181 if (!mSatelliteEntitlementStatusPerCarrier.get(subId, false)) { 4182 addAttachRestrictionForCarrier(subId, 4183 SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT, callback); 4184 } 4185 } 4186 } 4187 4188 /** 4189 * Save user setting for enabling satellite attach for the carrier associated with the 4190 * {@code subId} to persistent storage. 4191 * 4192 * @param subId Subscription ID. 4193 * 4194 * @return {@code true} if persist successful, {@code false} otherwise. 4195 */ 4196 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) persistSatelliteAttachEnabledForCarrierSetting(int subId)4197 protected boolean persistSatelliteAttachEnabledForCarrierSetting(int subId) { 4198 plogd("persistSatelliteAttachEnabledForCarrierSetting"); 4199 if (!isValidSubscriptionId(subId)) { 4200 ploge("persistSatelliteAttachEnabledForCarrierSetting: subId is not valid," 4201 + " subId=" + subId); 4202 return false; 4203 } 4204 4205 synchronized (mIsSatelliteEnabledLock) { 4206 try { 4207 mSubscriptionManagerService.setSubscriptionProperty(subId, 4208 SATELLITE_ATTACH_ENABLED_FOR_CARRIER, 4209 mSatelliteAttachRestrictionForCarrierArray.get(subId) 4210 .contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER) 4211 ? "0" : "1"); 4212 } catch (IllegalArgumentException | SecurityException ex) { 4213 ploge("persistSatelliteAttachEnabledForCarrierSetting, ex=" + ex); 4214 return false; 4215 } 4216 } 4217 return true; 4218 } 4219 4220 /** 4221 * Evaluate whether satellite attach for carrier should be restricted. 4222 * 4223 * @param subId Subscription Id to evaluate for. 4224 * @return {@code true} satellite attach is restricted, {@code false} otherwise. 4225 */ isSatelliteRestrictedForCarrier(int subId)4226 private boolean isSatelliteRestrictedForCarrier(int subId) { 4227 return !isSatelliteAttachEnabledForCarrierByUser(subId) 4228 || hasReasonToRestrictSatelliteCommunicationForCarrier(subId); 4229 } 4230 4231 /** 4232 * Check whether satellite is enabled for carrier at modem. 4233 * 4234 * @param subId Subscription ID to check for. 4235 * @return {@code true} if satellite modem is enabled, {@code false} otherwise. 4236 */ isSatelliteEnabledForCarrierAtModem(int subId)4237 private boolean isSatelliteEnabledForCarrierAtModem(int subId) { 4238 synchronized (mIsSatelliteEnabledLock) { 4239 return mIsSatelliteAttachEnabledForCarrierArrayPerSub.getOrDefault(subId, false); 4240 } 4241 } 4242 4243 /** 4244 * Evaluate whether satellite modem for carrier should be enabled or not. 4245 * <p> 4246 * Satellite will be enabled only when the following conditions are met: 4247 * <ul> 4248 * <li>Users want to enable it.</li> 4249 * <li>There is no satellite communication restriction, which is added by 4250 * {@link #addAttachRestrictionForCarrier(int, int, IIntegerConsumer)}</li> 4251 * <li>The carrier config {@link 4252 * android.telephony.CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} is set to 4253 * {@code true}.</li> 4254 * </ul> 4255 * 4256 * @param subId Subscription Id for evaluate for. 4257 * @param callback The callback for getting the result of enabling satellite. 4258 */ evaluateEnablingSatelliteForCarrier(int subId, int reason, @Nullable Consumer<Integer> callback)4259 private void evaluateEnablingSatelliteForCarrier(int subId, int reason, 4260 @Nullable Consumer<Integer> callback) { 4261 if (callback == null) { 4262 callback = errorCode -> plogd("evaluateEnablingSatelliteForCarrier: " 4263 + "SetSatelliteAttachEnableForCarrier error code =" + errorCode); 4264 } 4265 4266 if (!isSatelliteSupportedViaCarrier(subId)) { 4267 plogd("Satellite for carrier is not supported. Only user setting is stored"); 4268 callback.accept(SATELLITE_RESULT_SUCCESS); 4269 return; 4270 } 4271 4272 /* Request to enable or disable the satellite in the cellular modem only when the desired 4273 state and the current state are different. */ 4274 boolean isSatelliteExpectedToBeEnabled = !isSatelliteRestrictedForCarrier(subId); 4275 if (isSatelliteExpectedToBeEnabled != isSatelliteEnabledForCarrierAtModem(subId)) { 4276 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 4277 int simSlot = SubscriptionManager.getSlotIndex(subId); 4278 RequestHandleSatelliteAttachRestrictionForCarrierArgument argument = 4279 new RequestHandleSatelliteAttachRestrictionForCarrierArgument(subId, 4280 reason, callback); 4281 SatelliteControllerHandlerRequest request = 4282 new SatelliteControllerHandlerRequest(argument, 4283 SatelliteServiceUtils.getPhone(subId)); 4284 Message onCompleted = obtainMessage( 4285 EVENT_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE_DONE, request); 4286 mSatelliteModemInterface.requestSetSatelliteEnabledForCarrier(simSlot, 4287 isSatelliteExpectedToBeEnabled, onCompleted); 4288 } else { 4289 callback.accept(SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE); 4290 } 4291 } else { 4292 callback.accept(SATELLITE_RESULT_SUCCESS); 4293 } 4294 } 4295 evaluateOemSatelliteRequestAllowed( boolean isProvisionRequired)4296 @SatelliteManager.SatelliteResult private int evaluateOemSatelliteRequestAllowed( 4297 boolean isProvisionRequired) { 4298 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 4299 plogd("oemEnabledSatelliteFlag is disabled"); 4300 return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED; 4301 } 4302 if (!mSatelliteModemInterface.isSatelliteServiceSupported()) { 4303 plogd("evaluateOemSatelliteRequestAllowed: satellite service is not supported"); 4304 return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED; 4305 } 4306 4307 Boolean satelliteSupported = isSatelliteSupportedViaOemInternal(); 4308 if (satelliteSupported == null) { 4309 plogd("evaluateOemSatelliteRequestAllowed: satelliteSupported is null"); 4310 return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 4311 } 4312 if (!satelliteSupported) { 4313 return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED; 4314 } 4315 4316 if (isProvisionRequired) { 4317 Boolean satelliteProvisioned = isSatelliteViaOemProvisioned(); 4318 if (satelliteProvisioned == null) { 4319 plogd("evaluateOemSatelliteRequestAllowed: satelliteProvisioned is null"); 4320 return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 4321 } 4322 if (!satelliteProvisioned) { 4323 return SatelliteManager.SATELLITE_RESULT_SERVICE_NOT_PROVISIONED; 4324 } 4325 } 4326 4327 return SATELLITE_RESULT_SUCCESS; 4328 } 4329 4330 /** 4331 * Returns the non-terrestrial network radio technology that the satellite modem currently 4332 * supports. If multiple technologies are available, returns the first supported technology. 4333 */ 4334 @VisibleForTesting getSupportedNtnRadioTechnology()4335 protected @SatelliteManager.NTRadioTechnology int getSupportedNtnRadioTechnology() { 4336 synchronized (mSatelliteCapabilitiesLock) { 4337 if (mSatelliteCapabilities != null) { 4338 return mSatelliteCapabilities.getSupportedRadioTechnologies() 4339 .stream().findFirst().orElse(SatelliteManager.NT_RADIO_TECHNOLOGY_UNKNOWN); 4340 } 4341 return SatelliteManager.NT_RADIO_TECHNOLOGY_UNKNOWN; 4342 } 4343 } 4344 sendErrorAndReportSessionMetrics(@atelliteManager.SatelliteResult int error, Consumer<Integer> result)4345 private void sendErrorAndReportSessionMetrics(@SatelliteManager.SatelliteResult int error, 4346 Consumer<Integer> result) { 4347 result.accept(error); 4348 mSessionMetricsStats.setInitializationResult(error) 4349 .setSatelliteTechnology(getSupportedNtnRadioTechnology()) 4350 .setIsDemoMode(mIsDemoModeEnabled) 4351 .reportSessionMetrics(); 4352 mSessionStartTimeStamp = 0; 4353 mSessionProcessingTimeStamp = 0; 4354 } 4355 registerForServiceStateChanged()4356 private void registerForServiceStateChanged() { 4357 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 4358 return; 4359 } 4360 for (Phone phone : PhoneFactory.getPhones()) { 4361 phone.registerForServiceStateChanged(this, EVENT_SERVICE_STATE_CHANGED, null); 4362 } 4363 } 4364 handleEventServiceStateChanged()4365 private void handleEventServiceStateChanged() { 4366 handleServiceStateForSatelliteConnectionViaCarrier(); 4367 determineSystemNotification(); 4368 } 4369 handleServiceStateForSatelliteConnectionViaCarrier()4370 private void handleServiceStateForSatelliteConnectionViaCarrier() { 4371 for (Phone phone : PhoneFactory.getPhones()) { 4372 int subId = phone.getSubId(); 4373 ServiceState serviceState = phone.getServiceState(); 4374 if (serviceState == null) { 4375 continue; 4376 } 4377 4378 synchronized (mSatelliteConnectedLock) { 4379 CarrierRoamingSatelliteSessionStats sessionStats = 4380 mCarrierRoamingSatelliteSessionStatsMap.get(subId); 4381 4382 if (serviceState.isUsingNonTerrestrialNetwork()) { 4383 if (sessionStats != null) { 4384 sessionStats.onSignalStrength(phone); 4385 if (!mWasSatelliteConnectedViaCarrier.get(subId)) { 4386 // Log satellite connection start 4387 sessionStats.onConnectionStart(phone); 4388 } 4389 } 4390 4391 resetCarrierRoamingSatelliteModeParams(subId); 4392 mWasSatelliteConnectedViaCarrier.put(subId, true); 4393 4394 for (NetworkRegistrationInfo nri 4395 : serviceState.getNetworkRegistrationInfoList()) { 4396 if (nri.isNonTerrestrialNetwork()) { 4397 mSatModeCapabilitiesForCarrierRoaming.put(subId, 4398 nri.getAvailableServices()); 4399 } 4400 } 4401 } else { 4402 Boolean connected = mWasSatelliteConnectedViaCarrier.get(subId); 4403 if (getWwanIsInService(serviceState)) { 4404 resetCarrierRoamingSatelliteModeParams(subId); 4405 } else if (connected != null && connected) { 4406 // The device just got disconnected from a satellite network 4407 // and is not connected to any terrestrial network that has coverage 4408 mLastSatelliteDisconnectedTimesMillis.put(subId, getElapsedRealtime()); 4409 4410 plogd("sendMessageDelayed subId:" + subId 4411 + " phoneId:" + phone.getPhoneId() 4412 + " time:" + getSatelliteConnectionHysteresisTimeMillis(subId)); 4413 sendMessageDelayed(obtainMessage(EVENT_NOTIFY_NTN_HYSTERESIS_TIMED_OUT, 4414 phone.getPhoneId()), 4415 getSatelliteConnectionHysteresisTimeMillis(subId)); 4416 4417 if (sessionStats != null) { 4418 // Log satellite connection end 4419 sessionStats.onConnectionEnd(); 4420 } 4421 } 4422 mWasSatelliteConnectedViaCarrier.put(subId, false); 4423 } 4424 updateLastNotifiedNtnModeAndNotify(phone); 4425 } 4426 } 4427 } 4428 updateLastNotifiedNtnModeAndNotify(@ullable Phone phone)4429 private void updateLastNotifiedNtnModeAndNotify(@Nullable Phone phone) { 4430 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) return; 4431 4432 if (phone == null) { 4433 return; 4434 } 4435 4436 int subId = phone.getSubId(); 4437 synchronized (mSatelliteConnectedLock) { 4438 boolean initialized = mInitialized.get(subId); 4439 boolean lastNotifiedNtnMode = mLastNotifiedNtnMode.get(subId); 4440 boolean currNtnMode = isInSatelliteModeForCarrierRoaming(phone); 4441 if (!initialized || lastNotifiedNtnMode != currNtnMode) { 4442 if (!initialized) mInitialized.put(subId, true); 4443 mLastNotifiedNtnMode.put(subId, currNtnMode); 4444 phone.notifyCarrierRoamingNtnModeChanged(currNtnMode); 4445 logCarrierRoamingSatelliteSessionStats(phone, lastNotifiedNtnMode, currNtnMode); 4446 } 4447 } 4448 } 4449 logCarrierRoamingSatelliteSessionStats(@onNull Phone phone, boolean lastNotifiedNtnMode, boolean currNtnMode)4450 private void logCarrierRoamingSatelliteSessionStats(@NonNull Phone phone, 4451 boolean lastNotifiedNtnMode, boolean currNtnMode) { 4452 synchronized (mSatelliteConnectedLock) { 4453 int subId = phone.getSubId(); 4454 if (!lastNotifiedNtnMode && currNtnMode) { 4455 // Log satellite session start 4456 CarrierRoamingSatelliteSessionStats sessionStats = 4457 CarrierRoamingSatelliteSessionStats.getInstance(subId); 4458 sessionStats.onSessionStart(phone.getCarrierId(), phone); 4459 mCarrierRoamingSatelliteSessionStatsMap.put(subId, sessionStats); 4460 } else if (lastNotifiedNtnMode && !currNtnMode) { 4461 // Log satellite session end 4462 CarrierRoamingSatelliteSessionStats sessionStats = 4463 mCarrierRoamingSatelliteSessionStatsMap.get(subId); 4464 sessionStats.onSessionEnd(); 4465 mCarrierRoamingSatelliteSessionStatsMap.remove(subId); 4466 } 4467 } 4468 } 4469 getSatelliteConnectionHysteresisTimeMillis(int subId)4470 private long getSatelliteConnectionHysteresisTimeMillis(int subId) { 4471 PersistableBundle config = getPersistableBundle(subId); 4472 return (config.getInt( 4473 KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT) * 1000L); 4474 } 4475 persistOemEnabledSatelliteProvisionStatus(boolean isProvisioned)4476 private void persistOemEnabledSatelliteProvisionStatus(boolean isProvisioned) { 4477 synchronized (mSatelliteViaOemProvisionLock) { 4478 plogd("persistOemEnabledSatelliteProvisionStatus: isProvisioned=" + isProvisioned); 4479 4480 if (!loadSatelliteSharedPreferences()) return; 4481 4482 if (mSharedPreferences == null) { 4483 ploge("persistOemEnabledSatelliteProvisionStatus: mSharedPreferences is null"); 4484 } else { 4485 mSharedPreferences.edit().putBoolean( 4486 OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY, isProvisioned).apply(); 4487 } 4488 } 4489 } 4490 getPersistedOemEnabledSatelliteProvisionStatus()4491 private boolean getPersistedOemEnabledSatelliteProvisionStatus() { 4492 synchronized (mSatelliteViaOemProvisionLock) { 4493 if (!loadSatelliteSharedPreferences()) return false; 4494 4495 if (mSharedPreferences == null) { 4496 ploge("getPersistedOemEnabledSatelliteProvisionStatus: mSharedPreferences is null"); 4497 return false; 4498 } else { 4499 return mSharedPreferences.getBoolean( 4500 OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY, false); 4501 } 4502 } 4503 } 4504 loadSatelliteSharedPreferences()4505 private boolean loadSatelliteSharedPreferences() { 4506 if (mSharedPreferences == null) { 4507 try { 4508 mSharedPreferences = 4509 mContext.getSharedPreferences(SATELLITE_SHARED_PREF, 4510 Context.MODE_PRIVATE); 4511 } catch (Exception e) { 4512 ploge("loadSatelliteSharedPreferences: Cannot get default " 4513 + "shared preferences, e=" + e); 4514 return false; 4515 } 4516 } 4517 return true; 4518 } 4519 handleIsSatelliteProvisionedDoneEvent(@onNull AsyncResult ar)4520 private void handleIsSatelliteProvisionedDoneEvent(@NonNull AsyncResult ar) { 4521 SatelliteControllerHandlerRequest request = (SatelliteControllerHandlerRequest) ar.userObj; 4522 int error = SatelliteServiceUtils.getSatelliteError( 4523 ar, "handleIsSatelliteProvisionedDoneEvent"); 4524 boolean isSatelliteProvisionedInModem = false; 4525 if (error == SATELLITE_RESULT_SUCCESS) { 4526 if (ar.result == null) { 4527 ploge("handleIsSatelliteProvisionedDoneEvent: result is null"); 4528 error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 4529 } else { 4530 isSatelliteProvisionedInModem = ((int[]) ar.result)[0] == 1; 4531 } 4532 } else if (error == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) { 4533 plogd("handleIsSatelliteProvisionedDoneEvent: Modem does not support this request"); 4534 isSatelliteProvisionedInModem = true; 4535 } 4536 boolean isSatelliteViaOemProvisioned = 4537 isSatelliteProvisionedInModem && getPersistedOemEnabledSatelliteProvisionStatus(); 4538 plogd("isSatelliteProvisionedInModem=" + isSatelliteProvisionedInModem 4539 + ", isSatelliteViaOemProvisioned=" + isSatelliteViaOemProvisioned); 4540 Bundle bundle = new Bundle(); 4541 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED, isSatelliteViaOemProvisioned); 4542 synchronized (mSatelliteViaOemProvisionLock) { 4543 mIsSatelliteViaOemProvisioned = isSatelliteViaOemProvisioned; 4544 } 4545 ((ResultReceiver) request.argument).send(error, bundle); 4546 } 4547 getWaitForSatelliteEnablingResponseTimeoutMillis()4548 private long getWaitForSatelliteEnablingResponseTimeoutMillis() { 4549 return mContext.getResources().getInteger( 4550 R.integer.config_wait_for_satellite_enabling_response_timeout_millis); 4551 } 4552 startWaitForSatelliteEnablingResponseTimer( @onNull RequestSatelliteEnabledArgument argument)4553 private void startWaitForSatelliteEnablingResponseTimer( 4554 @NonNull RequestSatelliteEnabledArgument argument) { 4555 synchronized (mSatelliteEnabledRequestLock) { 4556 if (hasMessages(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT, argument)) { 4557 plogd("WaitForSatelliteEnablingResponseTimer of request ID " 4558 + argument.requestId + " was already started"); 4559 return; 4560 } 4561 plogd("Start timer to wait for response of the satellite enabling request ID=" 4562 + argument.requestId + ", enableSatellite=" + argument.enableSatellite 4563 + ", mWaitTimeForSatelliteEnablingResponse=" 4564 + mWaitTimeForSatelliteEnablingResponse); 4565 sendMessageDelayed(obtainMessage(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT, 4566 argument), mWaitTimeForSatelliteEnablingResponse); 4567 } 4568 } 4569 stopWaitForSatelliteEnablingResponseTimer( @onNull RequestSatelliteEnabledArgument argument)4570 private void stopWaitForSatelliteEnablingResponseTimer( 4571 @NonNull RequestSatelliteEnabledArgument argument) { 4572 synchronized (mSatelliteEnabledRequestLock) { 4573 plogd("Stop timer to wait for response of the satellite enabling request ID=" 4574 + argument.requestId + ", enableSatellite=" + argument.enableSatellite); 4575 removeMessages(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT, argument); 4576 } 4577 } 4578 shouldProcessEventSetSatelliteEnabledDone( @onNull RequestSatelliteEnabledArgument argument)4579 private boolean shouldProcessEventSetSatelliteEnabledDone( 4580 @NonNull RequestSatelliteEnabledArgument argument) { 4581 synchronized (mSatelliteEnabledRequestLock) { 4582 if (hasMessages(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT, argument)) { 4583 return true; 4584 } 4585 return false; 4586 } 4587 } 4588 handleEventWaitForSatelliteEnablingResponseTimedOut( @onNull RequestSatelliteEnabledArgument argument)4589 private void handleEventWaitForSatelliteEnablingResponseTimedOut( 4590 @NonNull RequestSatelliteEnabledArgument argument) { 4591 plogw("Timed out to wait for response of the satellite enabling request ID=" 4592 + argument.requestId + ", enableSatellite=" + argument.enableSatellite); 4593 4594 synchronized (mSatelliteEnabledRequestLock) { 4595 if (mSatelliteEnabledRequest != null) { 4596 if (mSatelliteEnabledRequest.enableSatellite && !argument.enableSatellite 4597 && mWaitingForRadioDisabled) { 4598 // Previous mSatelliteEnabledRequest is successful but waiting for 4599 // all radios to be turned off. 4600 mSatelliteEnabledRequest.callback.accept(SATELLITE_RESULT_SUCCESS); 4601 resetSatelliteEnabledRequest(); 4602 } else if (mSatelliteEnabledRequest.requestId == argument.requestId) { 4603 resetSatelliteEnabledRequest(); 4604 } 4605 } 4606 } 4607 argument.callback.accept(SATELLITE_RESULT_MODEM_TIMEOUT); 4608 4609 synchronized (mIsSatelliteEnabledLock) { 4610 if (argument.enableSatellite) { 4611 if (!mWaitingForDisableSatelliteModemResponse && !mWaitingForSatelliteModemOff) { 4612 resetSatelliteEnabledRequest(); 4613 IIntegerConsumer callback = new IIntegerConsumer.Stub() { 4614 @Override 4615 public void accept(int result) { 4616 plogd("handleEventWaitForSatelliteEnablingResponseTimedOut: " 4617 + "disable satellite result=" + result); 4618 } 4619 }; 4620 Consumer<Integer> result = 4621 FunctionalUtils.ignoreRemoteException(callback::accept); 4622 RequestSatelliteEnabledArgument request = new RequestSatelliteEnabledArgument( 4623 false, false, false, result); 4624 synchronized (mSatelliteEnabledRequestLock) { 4625 mSatelliteEnabledRequest = request; 4626 } 4627 sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null); 4628 } 4629 notifyEnablementFailedToSatelliteSessionController(); 4630 mControllerMetricsStats.reportServiceEnablementFailCount(); 4631 mSessionMetricsStats.setInitializationResult(SATELLITE_RESULT_MODEM_TIMEOUT) 4632 .setSatelliteTechnology(getSupportedNtnRadioTechnology()) 4633 .setInitializationProcessingTime( 4634 System.currentTimeMillis() - mSessionProcessingTimeStamp) 4635 .setIsDemoMode(mIsDemoModeEnabled) 4636 .reportSessionMetrics(); 4637 mSessionStartTimeStamp = 0; 4638 mSessionProcessingTimeStamp = 0; 4639 } else { 4640 /* 4641 * Unregister Importance Listener for Pointing UI when Satellite is disabled 4642 */ 4643 synchronized (mNeedsSatellitePointingLock) { 4644 if (mNeedsSatellitePointing) { 4645 mPointingAppController.removeListenerForPointingUI(); 4646 } 4647 } 4648 moveSatelliteToOffStateAndCleanUpResources(SATELLITE_RESULT_MODEM_TIMEOUT, null); 4649 mControllerMetricsStats.onSatelliteDisabled(); 4650 mWaitingForDisableSatelliteModemResponse = false; 4651 mWaitingForSatelliteModemOff = false; 4652 mSessionMetricsStats.setTerminationResult(SATELLITE_RESULT_MODEM_TIMEOUT) 4653 .setSatelliteTechnology(getSupportedNtnRadioTechnology()) 4654 .setTerminationProcessingTime( 4655 System.currentTimeMillis() - mSessionProcessingTimeStamp) 4656 .setSessionDurationSec(calculateSessionDurationTimeSec()) 4657 .reportSessionMetrics(); 4658 mSessionStartTimeStamp = 0; 4659 mSessionProcessingTimeStamp = 0; 4660 } 4661 } 4662 } 4663 handleCmdUpdateNtnSignalStrengthReporting(boolean shouldReport)4664 private void handleCmdUpdateNtnSignalStrengthReporting(boolean shouldReport) { 4665 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 4666 plogd("handleCmdUpdateNtnSignalStrengthReporting: oemEnabledSatelliteFlag is " 4667 + "disabled"); 4668 return; 4669 } 4670 4671 if (!isSatelliteEnabled()) { 4672 plogd("handleCmdUpdateNtnSignalStrengthReporting: ignore request, satellite is " 4673 + "disabled"); 4674 return; 4675 } 4676 4677 mLatestRequestedStateForNtnSignalStrengthReport.set(shouldReport); 4678 if (mIsModemEnabledReportingNtnSignalStrength.get() == shouldReport) { 4679 plogd("handleCmdUpdateNtnSignalStrengthReporting: ignore request. " 4680 + "mIsModemEnabledReportingNtnSignalStrength=" 4681 + mIsModemEnabledReportingNtnSignalStrength.get()); 4682 return; 4683 } 4684 4685 updateNtnSignalStrengthReporting(shouldReport); 4686 } 4687 updateNtnSignalStrengthReporting(boolean shouldReport)4688 private void updateNtnSignalStrengthReporting(boolean shouldReport) { 4689 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 4690 plogd("updateNtnSignalStrengthReporting: oemEnabledSatelliteFlag is " 4691 + "disabled"); 4692 return; 4693 } 4694 4695 SatelliteControllerHandlerRequest request = new SatelliteControllerHandlerRequest( 4696 shouldReport, SatelliteServiceUtils.getPhone()); 4697 Message onCompleted = obtainMessage(EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE, 4698 request); 4699 if (shouldReport) { 4700 plogd("updateNtnSignalStrengthReporting: startSendingNtnSignalStrength"); 4701 mSatelliteModemInterface.startSendingNtnSignalStrength(onCompleted); 4702 } else { 4703 plogd("updateNtnSignalStrengthReporting: stopSendingNtnSignalStrength"); 4704 mSatelliteModemInterface.stopSendingNtnSignalStrength(onCompleted); 4705 } 4706 } 4707 4708 /** 4709 * This API can be used by only CTS to override the cached value for the device overlay config 4710 * value : config_send_satellite_datagram_to_modem_in_demo_mode, which determines whether 4711 * outgoing satellite datagrams should be sent to modem in demo mode. 4712 * 4713 * @param shouldSendToModemInDemoMode Whether send datagram in demo mode should be sent to 4714 * satellite modem or not. 4715 * 4716 * @return {@code true} if the operation is successful, {@code false} otherwise. 4717 */ setShouldSendDatagramToModemInDemoMode(boolean shouldSendToModemInDemoMode)4718 public boolean setShouldSendDatagramToModemInDemoMode(boolean shouldSendToModemInDemoMode) { 4719 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 4720 plogd("setShouldSendDatagramToModemInDemoMode: oemEnabledSatelliteFlag is disabled"); 4721 return false; 4722 } 4723 4724 if (!isMockModemAllowed()) { 4725 plogd("setShouldSendDatagramToModemInDemoMode: mock modem not allowed."); 4726 return false; 4727 } 4728 4729 mDatagramController.setShouldSendDatagramToModemInDemoMode(shouldSendToModemInDemoMode); 4730 return true; 4731 } 4732 determineSystemNotification()4733 private void determineSystemNotification() { 4734 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) { 4735 logd("determineSystemNotification: carrierEnabledSatelliteFlag is disabled"); 4736 return; 4737 } 4738 4739 Pair<Boolean, Integer> isNtn = isUsingNonTerrestrialNetworkViaCarrier(); 4740 if (isNtn.first) { 4741 if (mSharedPreferences == null) { 4742 try { 4743 mSharedPreferences = mContext.getSharedPreferences(SATELLITE_SHARED_PREF, 4744 Context.MODE_PRIVATE); 4745 } catch (Exception e) { 4746 loge("Cannot get default shared preferences: " + e); 4747 } 4748 } 4749 if (mSharedPreferences == null) { 4750 loge("determineSystemNotification: Cannot get default shared preferences"); 4751 return; 4752 } 4753 if (!mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false)) { 4754 showSatelliteSystemNotification(isNtn.second); 4755 mSharedPreferences.edit().putBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, 4756 true).apply(); 4757 } 4758 } 4759 } 4760 showSatelliteSystemNotification(int subId)4761 private void showSatelliteSystemNotification(int subId) { 4762 plogd("showSatelliteSystemNotification"); 4763 final NotificationChannel notificationChannel = new NotificationChannel( 4764 NOTIFICATION_CHANNEL_ID, 4765 NOTIFICATION_CHANNEL, 4766 NotificationManager.IMPORTANCE_DEFAULT 4767 ); 4768 notificationChannel.setSound(null, null); 4769 NotificationManager notificationManager = mContext.getSystemService( 4770 NotificationManager.class); 4771 notificationManager.createNotificationChannel(notificationChannel); 4772 4773 Notification.Builder notificationBuilder = new Notification.Builder(mContext) 4774 .setContentTitle(mContext.getResources().getString( 4775 R.string.satellite_notification_title)) 4776 .setContentText(mContext.getResources().getString( 4777 R.string.satellite_notification_summary)) 4778 .setSmallIcon(R.drawable.ic_android_satellite_24px) 4779 .setChannelId(NOTIFICATION_CHANNEL_ID) 4780 .setAutoCancel(true) 4781 .setColor(mContext.getColor( 4782 com.android.internal.R.color.system_notification_accent_color)) 4783 .setVisibility(Notification.VISIBILITY_PUBLIC); 4784 4785 // Add action to invoke message application. 4786 // getDefaultSmsPackage and getLaunchIntentForPackage are nullable. 4787 Optional<Intent> nullableIntent = Optional.ofNullable( 4788 Telephony.Sms.getDefaultSmsPackage(mContext)) 4789 .flatMap(packageName -> { 4790 PackageManager pm = mContext.getPackageManager(); 4791 return Optional.ofNullable(pm.getLaunchIntentForPackage(packageName)); 4792 }); 4793 // If nullableIntent is null, create new Intent for most common way to invoke message app. 4794 Intent finalIntent = nullableIntent.map(intent -> { 4795 // Invoke the home screen of default message application. 4796 intent.setAction(Intent.ACTION_MAIN); 4797 intent.addCategory(Intent.CATEGORY_HOME); 4798 return intent; 4799 }).orElseGet(() -> { 4800 ploge("showSatelliteSystemNotification: no default sms package name, Invoke " 4801 + "default sms compose window instead"); 4802 Intent newIntent = new Intent(Intent.ACTION_VIEW); 4803 newIntent.setData(Uri.parse("sms:")); 4804 return newIntent; 4805 }); 4806 4807 PendingIntent pendingIntentOpenMessage = PendingIntent.getActivity(mContext, 0, 4808 finalIntent, PendingIntent.FLAG_IMMUTABLE); 4809 Notification.Action actionOpenMessage = new Notification.Action.Builder(0, 4810 mContext.getResources().getString(R.string.satellite_notification_open_message), 4811 pendingIntentOpenMessage).build(); 4812 notificationBuilder.addAction(actionOpenMessage); 4813 4814 // Add action to invoke Satellite setting activity in Settings. 4815 Intent intentSatelliteSetting = new Intent(ACTION_SATELLITE_SETTING); 4816 intentSatelliteSetting.putExtra("sub_id", subId); 4817 PendingIntent pendingIntentSatelliteSetting = PendingIntent.getActivity(mContext, 0, 4818 intentSatelliteSetting, PendingIntent.FLAG_IMMUTABLE); 4819 4820 Notification.Action actionOpenSatelliteSetting = new Notification.Action.Builder(null, 4821 mContext.getResources().getString(R.string.satellite_notification_how_it_works), 4822 pendingIntentSatelliteSetting).build(); 4823 notificationBuilder.addAction(actionOpenSatelliteSetting); 4824 4825 notificationManager.notifyAsUser(NOTIFICATION_TAG, NOTIFICATION_ID, 4826 notificationBuilder.build(), UserHandle.ALL); 4827 4828 mCarrierRoamingSatelliteControllerStats.reportCountOfSatelliteNotificationDisplayed(); 4829 } 4830 resetCarrierRoamingSatelliteModeParams()4831 private void resetCarrierRoamingSatelliteModeParams() { 4832 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) return; 4833 4834 for (Phone phone : PhoneFactory.getPhones()) { 4835 resetCarrierRoamingSatelliteModeParams(phone.getSubId()); 4836 } 4837 } 4838 resetCarrierRoamingSatelliteModeParams(int subId)4839 private void resetCarrierRoamingSatelliteModeParams(int subId) { 4840 if (!mFeatureFlags.carrierEnabledSatelliteFlag()) return; 4841 4842 synchronized (mSatelliteConnectedLock) { 4843 mLastSatelliteDisconnectedTimesMillis.put(subId, null); 4844 mSatModeCapabilitiesForCarrierRoaming.remove(subId); 4845 mWasSatelliteConnectedViaCarrier.put(subId, false); 4846 } 4847 } 4848 4849 @NonNull getPersistableBundle(int subId)4850 private PersistableBundle getPersistableBundle(int subId) { 4851 synchronized (mCarrierConfigArrayLock) { 4852 PersistableBundle config = mCarrierConfigArray.get(subId); 4853 if (config == null) { 4854 config = getConfigForSubId(subId); 4855 mCarrierConfigArray.put(subId, config); 4856 } 4857 return config; 4858 } 4859 } 4860 4861 // Should be invoked only when session termination done or session termination failed. calculateSessionDurationTimeSec()4862 private int calculateSessionDurationTimeSec() { 4863 return (int) ( 4864 (System.currentTimeMillis() - mSessionStartTimeStamp 4865 - mSessionMetricsStats.getSessionInitializationProcessingTimeMillis() 4866 - mSessionMetricsStats.getSessionTerminationProcessingTimeMillis()) / 1000); 4867 } 4868 notifyEnablementFailedToSatelliteSessionController()4869 private void notifyEnablementFailedToSatelliteSessionController() { 4870 if (mSatelliteSessionController != null) { 4871 mSatelliteSessionController.onSatelliteEnablementFailed(); 4872 } else { 4873 ploge("notifyEnablementFailedToSatelliteSessionController: mSatelliteSessionController" 4874 + " is not initialized yet"); 4875 } 4876 } 4877 getDemoPointingAlignedDurationMillisFromResources()4878 private long getDemoPointingAlignedDurationMillisFromResources() { 4879 long durationMillis = 15000L; 4880 try { 4881 durationMillis = mContext.getResources().getInteger( 4882 R.integer.config_demo_pointing_aligned_duration_millis); 4883 } catch (Resources.NotFoundException ex) { 4884 loge("getPointingAlignedDurationMillis: ex=" + ex); 4885 } 4886 4887 return durationMillis; 4888 } 4889 4890 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) getDemoPointingAlignedDurationMillis()4891 public long getDemoPointingAlignedDurationMillis() { 4892 return mDemoPointingAlignedDurationMillis; 4893 } 4894 getDemoPointingNotAlignedDurationMillisFromResources()4895 private long getDemoPointingNotAlignedDurationMillisFromResources() { 4896 long durationMillis = 30000L; 4897 try { 4898 durationMillis = mContext.getResources().getInteger( 4899 R.integer.config_demo_pointing_not_aligned_duration_millis); 4900 } catch (Resources.NotFoundException ex) { 4901 loge("getPointingNotAlignedDurationMillis: ex=" + ex); 4902 } 4903 4904 return durationMillis; 4905 } 4906 4907 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) getDemoPointingNotAlignedDurationMillis()4908 public long getDemoPointingNotAlignedDurationMillis() { 4909 return mDemoPointingNotAlignedDurationMillis; 4910 } 4911 getWwanIsInService(ServiceState serviceState)4912 private boolean getWwanIsInService(ServiceState serviceState) { 4913 List<NetworkRegistrationInfo> nriList = serviceState 4914 .getNetworkRegistrationInfoListForTransportType( 4915 AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 4916 for (NetworkRegistrationInfo nri : nriList) { 4917 if (nri.isInService()) { 4918 logv("getWwanIsInService: return true"); 4919 return true; 4920 } 4921 } 4922 4923 logv("getWwanIsInService: return false"); 4924 return false; 4925 } 4926 logv(@onNull String log)4927 private static void logv(@NonNull String log) { 4928 Rlog.v(TAG, log); 4929 } 4930 logd(@onNull String log)4931 private static void logd(@NonNull String log) { 4932 Rlog.d(TAG, log); 4933 } 4934 logw(@onNull String log)4935 private static void logw(@NonNull String log) { 4936 Rlog.w(TAG, log); 4937 } 4938 loge(@onNull String log)4939 private static void loge(@NonNull String log) { 4940 Rlog.e(TAG, log); 4941 } 4942 isSatellitePersistentLoggingEnabled( @onNull Context context, @NonNull FeatureFlags featureFlags)4943 private boolean isSatellitePersistentLoggingEnabled( 4944 @NonNull Context context, @NonNull FeatureFlags featureFlags) { 4945 if (featureFlags.satellitePersistentLogging()) { 4946 return true; 4947 } 4948 try { 4949 return context.getResources().getBoolean( 4950 R.bool.config_dropboxmanager_persistent_logging_enabled); 4951 } catch (RuntimeException e) { 4952 return false; 4953 } 4954 } 4955 plogd(@onNull String log)4956 private void plogd(@NonNull String log) { 4957 Rlog.d(TAG, log); 4958 if (mPersistentLogger != null) { 4959 mPersistentLogger.debug(TAG, log); 4960 } 4961 } 4962 plogw(@onNull String log)4963 private void plogw(@NonNull String log) { 4964 Rlog.w(TAG, log); 4965 if (mPersistentLogger != null) { 4966 mPersistentLogger.warn(TAG, log); 4967 } 4968 } 4969 ploge(@onNull String log)4970 private void ploge(@NonNull String log) { 4971 Rlog.e(TAG, log); 4972 if (mPersistentLogger != null) { 4973 mPersistentLogger.error(TAG, log); 4974 } 4975 } 4976 handlePersistentLoggingOnSessionStart(RequestSatelliteEnabledArgument argument)4977 private void handlePersistentLoggingOnSessionStart(RequestSatelliteEnabledArgument argument) { 4978 if (mPersistentLogger == null) { 4979 return; 4980 } 4981 if (argument.isEmergency) { 4982 DropBoxManagerLoggerBackend.getInstance(mContext).setLoggingEnabled(true); 4983 } 4984 } 4985 handlePersistentLoggingOnSessionEnd(boolean isEmergency)4986 private void handlePersistentLoggingOnSessionEnd(boolean isEmergency) { 4987 if (mPersistentLogger == null) { 4988 return; 4989 } 4990 DropBoxManagerLoggerBackend loggerBackend = 4991 DropBoxManagerLoggerBackend.getInstance(mContext); 4992 // Flush persistent satellite logs on eSOS session end 4993 if (isEmergency) { 4994 loggerBackend.flushAsync(); 4995 } 4996 // Also turn off persisted logging until new session is started 4997 loggerBackend.setLoggingEnabled(false); 4998 } 4999 5000 /** 5001 * Set last emergency call time to the current time. 5002 */ setLastEmergencyCallTime()5003 public void setLastEmergencyCallTime() { 5004 synchronized (mLock) { 5005 mLastEmergencyCallTime = getElapsedRealtime(); 5006 plogd("mLastEmergencyCallTime=" + mLastEmergencyCallTime); 5007 } 5008 } 5009 5010 /** 5011 * Check if satellite is in emergency mode. 5012 */ isInEmergencyMode()5013 public boolean isInEmergencyMode() { 5014 synchronized (mLock) { 5015 if (mLastEmergencyCallTime == 0) return false; 5016 5017 long currentTime = getElapsedRealtime(); 5018 if ((currentTime - mLastEmergencyCallTime) <= mSatelliteEmergencyModeDurationMillis) { 5019 plogd("Satellite is in emergency mode"); 5020 return true; 5021 } 5022 return false; 5023 } 5024 } 5025 getSatelliteEmergencyModeDurationFromOverlayConfig(@onNull Context context)5026 private long getSatelliteEmergencyModeDurationFromOverlayConfig(@NonNull Context context) { 5027 Integer duration = DEFAULT_SATELLITE_EMERGENCY_MODE_DURATION_SECONDS; 5028 try { 5029 duration = context.getResources().getInteger(com.android.internal.R.integer 5030 .config_satellite_emergency_mode_duration); 5031 } catch (Resources.NotFoundException ex) { 5032 ploge("getSatelliteEmergencyModeDurationFromOverlayConfig: got ex=" + ex); 5033 } 5034 return TimeUnit.SECONDS.toMillis(duration); 5035 } 5036 } 5037