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.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY; 20 import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY; 21 import static android.provider.Settings.ACTION_SATELLITE_SETTING; 22 import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC; 23 import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL; 24 import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_TYPE; 25 import static android.telephony.CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL; 26 import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT; 27 import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT; 28 import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY; 29 import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT; 30 import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE; 31 import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT; 32 import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL; 33 import static android.telephony.CarrierConfigManager.KEY_REGIONAL_SATELLITE_EARFCN_BUNDLE; 34 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL; 35 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTED_NOTIFICATION_THROTTLE_MILLIS_INT; 36 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT; 37 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT; 38 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_DISPLAY_NAME_STRING; 39 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL; 40 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL; 41 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_NIDD_APN_NAME_STRING; 42 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT; 43 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT; 44 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL; 45 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT; 46 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL; 47 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE_BYTES_INT; 48 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SUPPORTED_MSG_APPS_STRING_ARRAY; 49 import static android.telephony.SubscriptionManager.SATELLITE_ATTACH_ENABLED_FOR_CARRIER; 50 import static android.telephony.SubscriptionManager.SATELLITE_ENTITLEMENT_STATUS; 51 import static android.telephony.SubscriptionManager.isValidSubscriptionId; 52 import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID; 53 import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE; 54 import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS; 55 import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911; 56 import static android.telephony.satellite.SatelliteManager.KEY_NTN_SIGNAL_STRENGTH; 57 import static android.telephony.satellite.SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT; 58 import static android.telephony.satellite.SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER; 59 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS; 60 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 61 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_ERROR; 62 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT; 63 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NO_VALID_SATELLITE_SUBSCRIPTION; 64 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED; 65 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED; 66 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS; 67 68 import static com.android.internal.telephony.configupdate.ConfigProviderAdaptor.DOMAIN_SATELLITE; 69 70 import android.annotation.ArrayRes; 71 import android.annotation.IntDef; 72 import android.annotation.NonNull; 73 import android.annotation.Nullable; 74 import android.app.AlertDialog; 75 import android.app.Notification; 76 import android.app.NotificationChannel; 77 import android.app.NotificationManager; 78 import android.app.PendingIntent; 79 import android.app.StatusBarManager; 80 import android.bluetooth.BluetoothAdapter; 81 import android.content.BroadcastReceiver; 82 import android.content.ComponentName; 83 import android.content.ContentResolver; 84 import android.content.Context; 85 import android.content.Intent; 86 import android.content.IntentFilter; 87 import android.content.SharedPreferences; 88 import android.content.pm.ApplicationInfo; 89 import android.content.pm.PackageManager; 90 import android.content.res.Configuration; 91 import android.content.res.Resources; 92 import android.database.ContentObserver; 93 import android.hardware.devicestate.DeviceState; 94 import android.hardware.devicestate.DeviceStateManager; 95 import android.location.LocationManager; 96 import android.net.Uri; 97 import android.net.wifi.WifiManager; 98 import android.nfc.NfcAdapter; 99 import android.os.AsyncResult; 100 import android.os.Binder; 101 import android.os.Build; 102 import android.os.Bundle; 103 import android.os.CancellationSignal; 104 import android.os.Handler; 105 import android.os.HandlerExecutor; 106 import android.os.HandlerThread; 107 import android.os.IBinder; 108 import android.os.ICancellationSignal; 109 import android.os.Looper; 110 import android.os.Message; 111 import android.os.PersistableBundle; 112 import android.os.Registrant; 113 import android.os.RegistrantList; 114 import android.os.RemoteException; 115 import android.os.ResultReceiver; 116 import android.os.ServiceSpecificException; 117 import android.os.SystemClock; 118 import android.os.SystemProperties; 119 import android.os.UserHandle; 120 import android.provider.Settings; 121 import android.provider.Telephony; 122 import android.telecom.TelecomManager; 123 import android.telephony.AccessNetworkConstants; 124 import android.telephony.AnomalyReporter; 125 import android.telephony.CarrierConfigManager; 126 import android.telephony.DropBoxManagerLoggerBackend; 127 import android.telephony.NetworkRegistrationInfo; 128 import android.telephony.PersistentLogger; 129 import android.telephony.Rlog; 130 import android.telephony.ServiceState; 131 import android.telephony.SubscriptionInfo; 132 import android.telephony.SubscriptionManager; 133 import android.telephony.TelephonyManager; 134 import android.telephony.TelephonyRegistryManager; 135 import android.telephony.satellite.INtnSignalStrengthCallback; 136 import android.telephony.satellite.ISatelliteCapabilitiesCallback; 137 import android.telephony.satellite.ISatelliteDatagramCallback; 138 import android.telephony.satellite.ISatelliteModemStateCallback; 139 import android.telephony.satellite.ISatelliteProvisionStateCallback; 140 import android.telephony.satellite.ISatelliteTransmissionUpdateCallback; 141 import android.telephony.satellite.ISelectedNbIotSatelliteSubscriptionCallback; 142 import android.telephony.satellite.NtnSignalStrength; 143 import android.telephony.satellite.SatelliteAccessConfiguration; 144 import android.telephony.satellite.SatelliteCapabilities; 145 import android.telephony.satellite.SatelliteCommunicationAccessStateCallback; 146 import android.telephony.satellite.SatelliteDatagram; 147 import android.telephony.satellite.SatelliteManager; 148 import android.telephony.satellite.SatelliteModemEnableRequestAttributes; 149 import android.telephony.satellite.SatelliteSubscriberInfo; 150 import android.telephony.satellite.SatelliteSubscriberProvisionStatus; 151 import android.telephony.satellite.SatelliteSubscriptionInfo; 152 import android.telephony.satellite.SystemSelectionSpecifier; 153 import android.text.TextUtils; 154 import android.util.Log; 155 import android.util.Pair; 156 import android.util.SparseArray; 157 import android.util.SparseBooleanArray; 158 import android.uwb.UwbManager; 159 import android.view.WindowManager; 160 161 import com.android.internal.R; 162 import com.android.internal.annotations.GuardedBy; 163 import com.android.internal.annotations.VisibleForTesting; 164 import com.android.internal.telephony.CommandsInterface; 165 import com.android.internal.telephony.DeviceStateMonitor; 166 import com.android.internal.telephony.IBooleanConsumer; 167 import com.android.internal.telephony.IIntegerConsumer; 168 import com.android.internal.telephony.Phone; 169 import com.android.internal.telephony.PhoneFactory; 170 import com.android.internal.telephony.TelephonyCountryDetector; 171 import com.android.internal.telephony.configupdate.ConfigParser; 172 import com.android.internal.telephony.configupdate.ConfigProviderAdaptor; 173 import com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver; 174 import com.android.internal.telephony.flags.FeatureFlags; 175 import com.android.internal.telephony.flags.Flags; 176 import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteControllerStats; 177 import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteSessionStats; 178 import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats; 179 import com.android.internal.telephony.satellite.metrics.ProvisionMetricsStats; 180 import com.android.internal.telephony.satellite.metrics.SessionMetricsStats; 181 import com.android.internal.telephony.subscription.SubscriptionInfoInternal; 182 import com.android.internal.telephony.subscription.SubscriptionManagerService; 183 import com.android.internal.telephony.util.ArrayUtils; 184 import com.android.internal.telephony.util.TelephonyUtils; 185 import com.android.internal.telephony.util.WorkerThread; 186 import com.android.internal.util.FunctionalUtils; 187 188 import java.lang.annotation.Retention; 189 import java.lang.annotation.RetentionPolicy; 190 import java.util.ArrayList; 191 import java.util.Arrays; 192 import java.util.Collections; 193 import java.util.HashMap; 194 import java.util.HashSet; 195 import java.util.List; 196 import java.util.Map; 197 import java.util.Optional; 198 import java.util.Set; 199 import java.util.TreeMap; 200 import java.util.UUID; 201 import java.util.concurrent.ConcurrentHashMap; 202 import java.util.concurrent.Executors; 203 import java.util.concurrent.TimeUnit; 204 import java.util.concurrent.atomic.AtomicBoolean; 205 import java.util.concurrent.atomic.AtomicLong; 206 import java.util.function.Consumer; 207 import java.util.stream.Collectors; 208 209 /** 210 * Satellite controller is the backend service of 211 * {@link android.telephony.satellite.SatelliteManager}. 212 */ 213 public class SatelliteController extends Handler { 214 private static final String TAG = "SatelliteController"; 215 /** Whether enabling verbose debugging message or not. */ 216 private static final boolean DBG = false; 217 private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem"; 218 private static final boolean DEBUG = !"user".equals(Build.TYPE); 219 /** File used to store shared preferences related to satellite. */ 220 public static final String SATELLITE_SHARED_PREF = "satellite_shared_pref"; 221 public static final String SATELLITE_SUBSCRIPTION_ID = "satellite_subscription_id"; 222 /** Value to pass for the setting key SATELLITE_MODE_ENABLED, enabled = 1, disabled = 0 */ 223 public static final int SATELLITE_MODE_ENABLED_TRUE = 1; 224 public static final int SATELLITE_MODE_ENABLED_FALSE = 0; 225 public static final int INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE = -1; 226 /** 227 * This is used by CTS to override the timeout duration to wait for the response of the request 228 * to enable satellite. 229 */ 230 public static final int TIMEOUT_TYPE_WAIT_FOR_SATELLITE_ENABLING_RESPONSE = 1; 231 /** This is used by CTS to override demo pointing aligned duration. */ 232 public static final int TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS = 2; 233 /** This is used by CTS to override demo pointing not aligned duration. */ 234 public static final int TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS = 3; 235 /** This is used by CTS to override evaluate esos profiles prioritization duration. */ 236 public static final int TIMEOUT_TYPE_EVALUATE_ESOS_PROFILES_PRIORITIZATION_DURATION_MILLIS = 4; 237 /** Key used to read/write OEM-enabled satellite provision status in shared preferences. */ 238 private static final String OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY = 239 "oem_enabled_satellite_provision_status_key"; 240 /** Key used to read/write default messages application NTN SMS support 241 * in shared preferences. */ 242 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 243 public static final String NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY = 244 "ntn_sms_supported_by_messages_app_key"; 245 public static final String CARRIER_ROAMING_NTN_ALL_SATELLITE_PLMN_SET_KEY = 246 "carrier_roaming_ntn_all_satellite_plmn_set_key"; 247 248 public static final long DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS = 249 TimeUnit.SECONDS.toMillis(30); 250 251 /** Sets report entitled metrics cool down to 23 hours to help enforcing privacy requirement.*/ 252 private static final long WAIT_FOR_REPORT_ENTITLED_MERTICS_TIMEOUT_MILLIS = 253 TimeUnit.HOURS.toMillis(23); 254 255 /** 256 * Delay SatelliteEnable request when network selection auto. current RIL not verified to 257 * response right after network selection auto changed. Some RIL has delay for waiting in-svc 258 * with Automatic selection request. 259 */ 260 private static final long DELAY_WAITING_SET_NETWORK_SELECTION_AUTO_MILLIS = 261 TimeUnit.SECONDS.toMillis(1); 262 263 /** Message codes used in handleMessage() */ 264 //TODO: Move the Commands and events related to position updates to PointingAppController 265 private static final int CMD_START_SATELLITE_TRANSMISSION_UPDATES = 1; 266 private static final int EVENT_START_SATELLITE_TRANSMISSION_UPDATES_DONE = 2; 267 private static final int CMD_STOP_SATELLITE_TRANSMISSION_UPDATES = 3; 268 private static final int EVENT_STOP_SATELLITE_TRANSMISSION_UPDATES_DONE = 4; 269 private static final int CMD_PROVISION_SATELLITE_SERVICE = 7; 270 private static final int EVENT_PROVISION_SATELLITE_SERVICE_DONE = 8; 271 private static final int CMD_DEPROVISION_SATELLITE_SERVICE = 9; 272 private static final int EVENT_DEPROVISION_SATELLITE_SERVICE_DONE = 10; 273 private static final int CMD_SET_SATELLITE_ENABLED = 11; 274 private static final int EVENT_SET_SATELLITE_ENABLED_DONE = 12; 275 private static final int CMD_IS_SATELLITE_ENABLED = 13; 276 private static final int EVENT_IS_SATELLITE_ENABLED_DONE = 14; 277 private static final int CMD_IS_SATELLITE_SUPPORTED = 15; 278 private static final int EVENT_IS_SATELLITE_SUPPORTED_DONE = 16; 279 private static final int CMD_GET_SATELLITE_CAPABILITIES = 17; 280 private static final int EVENT_GET_SATELLITE_CAPABILITIES_DONE = 18; 281 private static final int CMD_GET_TIME_SATELLITE_NEXT_VISIBLE = 21; 282 private static final int EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE = 22; 283 private static final int EVENT_RADIO_STATE_CHANGED = 23; 284 private static final int CMD_IS_SATELLITE_PROVISIONED = 24; 285 private static final int EVENT_IS_SATELLITE_PROVISIONED_DONE = 25; 286 private static final int EVENT_PENDING_DATAGRAMS = 27; 287 private static final int EVENT_SATELLITE_MODEM_STATE_CHANGED = 28; 288 private static final int EVENT_SET_SATELLITE_PLMN_INFO_DONE = 29; 289 private static final int CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE = 30; 290 private static final int EVENT_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE_DONE = 31; 291 private static final int CMD_REQUEST_NTN_SIGNAL_STRENGTH = 32; 292 private static final int EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE = 33; 293 private static final int EVENT_NTN_SIGNAL_STRENGTH_CHANGED = 34; 294 private static final int CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING = 35; 295 private static final int EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE = 36; 296 private static final int EVENT_SERVICE_STATE_CHANGED = 37; 297 private static final int EVENT_SATELLITE_CAPABILITIES_CHANGED = 38; 298 protected static final int EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT = 39; 299 private static final int EVENT_SATELLITE_CONFIG_DATA_UPDATED = 40; 300 private static final int EVENT_SATELLITE_SUPPORTED_STATE_CHANGED = 41; 301 private static final int EVENT_NOTIFY_NTN_HYSTERESIS_TIMED_OUT = 42; 302 private static final int CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION = 43; 303 private static final int CMD_UPDATE_PROVISION_SATELLITE_TOKEN = 44; 304 private static final int EVENT_UPDATE_PROVISION_SATELLITE_TOKEN_DONE = 45; 305 private static final int EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT = 46; 306 private static final int EVENT_WIFI_CONNECTIVITY_STATE_CHANGED = 47; 307 protected static final int EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT = 49; 308 private static final int CMD_UPDATE_SATELLITE_ENABLE_ATTRIBUTES = 50; 309 private static final int EVENT_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_DONE = 51; 310 protected static final int 311 EVENT_WAIT_FOR_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_RESPONSE_TIMED_OUT = 52; 312 private static final int EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT = 53; 313 protected static final int EVENT_SATELLITE_REGISTRATION_FAILURE = 54; 314 private static final int EVENT_TERRESTRIAL_NETWORK_AVAILABLE_CHANGED = 55; 315 private static final int EVENT_SET_NETWORK_SELECTION_AUTO_DONE = 56; 316 private static final int EVENT_SIGNAL_STRENGTH_CHANGED = 57; 317 private static final int CMD_UPDATE_SYSTEM_SELECTION_CHANNELS = 58; 318 private static final int EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE = 59; 319 private static final int EVENT_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_CHANGED = 60; 320 private static final int CMD_EVALUATE_CARRIER_ROAMING_NTN_ELIGIBILITY_CHANGE = 61; 321 private static final int CMD_LOCATION_SERVICE_STATE_CHANGED = 62; 322 protected static final int 323 EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT = 63; 324 private static final int CMD_GET_SATELLITE_ENABLED_FOR_CARRIER = 64; 325 private static final int EVENT_GET_SATELLITE_ENABLED_FOR_CARRIER_DONE = 65; 326 327 @NonNull private static SatelliteController sInstance; 328 @NonNull private final Context mContext; 329 @NonNull private final SatelliteModemInterface mSatelliteModemInterface; 330 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 331 @NonNull protected SatelliteSessionController mSatelliteSessionController; 332 @NonNull private final PointingAppController mPointingAppController; 333 @NonNull private final DatagramController mDatagramController; 334 @NonNull private final ControllerMetricsStats mControllerMetricsStats; 335 @NonNull private final ProvisionMetricsStats mProvisionMetricsStats; 336 @NonNull private SessionMetricsStats mSessionMetricsStats; 337 @NonNull private CarrierRoamingSatelliteControllerStats mCarrierRoamingSatelliteControllerStats; 338 339 @NonNull private final SubscriptionManagerService mSubscriptionManagerService; 340 @NonNull private final TelephonyCountryDetector mCountryDetector; 341 @NonNull private final TelecomManager mTelecomManager; 342 private final CommandsInterface mCi; 343 private ContentResolver mContentResolver; 344 private final DeviceStateMonitor mDSM; 345 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 346 protected final Object mSatellitePhoneLock = new Object(); 347 @GuardedBy("mSatellitePhoneLock") 348 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 349 protected Phone mSatellitePhone = null; 350 private SatelliteOptimizedApplicationsTracker mSatelliteOptimizedApplicationsTracker; 351 private final Object mRadioStateLock = new Object(); 352 353 /** Flags to indicate whether the respective radio is enabled */ 354 @GuardedBy("mRadioStateLock") 355 private boolean mBTStateEnabled = false; 356 @GuardedBy("mRadioStateLock") 357 private boolean mNfcStateEnabled = false; 358 @GuardedBy("mRadioStateLock") 359 private boolean mUwbStateEnabled = false; 360 @GuardedBy("mRadioStateLock") 361 private boolean mWifiStateEnabled = false; 362 363 // Flags to indicate that respective radios need to be disabled when satellite is enabled 364 private boolean mDisableBTOnSatelliteEnabled = false; 365 private boolean mDisableNFCOnSatelliteEnabled = false; 366 private boolean mDisableUWBOnSatelliteEnabled = false; 367 private boolean mDisableWifiOnSatelliteEnabled = false; 368 private AtomicBoolean mIgnorePlmnListFromStorage = new AtomicBoolean(false); 369 370 private final Object mSatelliteEnabledRequestLock = new Object(); 371 /* This variable is used to store the first enable request that framework has received in the 372 * current session. 373 */ 374 @GuardedBy("mSatelliteEnabledRequestLock") 375 private RequestSatelliteEnabledArgument mSatelliteEnabledRequest = null; 376 /* This variable is used to store a disable request that framework has received. 377 */ 378 @GuardedBy("mSatelliteEnabledRequestLock") 379 private RequestSatelliteEnabledArgument mSatelliteDisabledRequest = null; 380 /* This variable is used to store an enable request that updates the enable attributes of an 381 * existing satellite session. 382 */ 383 @GuardedBy("mSatelliteEnabledRequestLock") 384 private RequestSatelliteEnabledArgument mSatelliteEnableAttributesUpdateRequest = null; 385 /** Flag to indicate that satellite is enabled successfully 386 * and waiting for all the radios to be disabled so that success can be sent to callback 387 */ 388 @GuardedBy("mSatelliteEnabledRequestLock") 389 private boolean mWaitingForRadioDisabled = false; 390 @GuardedBy("mSatelliteEnabledRequestLock") 391 private boolean mWaitingForDisableSatelliteModemResponse = false; 392 @GuardedBy("mSatelliteEnabledRequestLock") 393 private boolean mWaitingForSatelliteModemOff = false; 394 395 private final AtomicBoolean mRegisteredForPendingDatagramCountWithSatelliteService = 396 new AtomicBoolean(false); 397 private final AtomicBoolean mRegisteredForSatelliteModemStateChangedWithSatelliteService = 398 new AtomicBoolean(false); 399 private final AtomicBoolean mRegisteredForNtnSignalStrengthChanged = new AtomicBoolean(false); 400 private final AtomicBoolean mRegisteredForSatelliteCapabilitiesChanged = 401 new AtomicBoolean(false); 402 private final AtomicBoolean mIsModemEnabledReportingNtnSignalStrength = 403 new AtomicBoolean(false); 404 private final AtomicBoolean mLatestRequestedStateForNtnSignalStrengthReport = 405 new AtomicBoolean(false); 406 private final AtomicBoolean mRegisteredForSatelliteSupportedStateChanged = 407 new AtomicBoolean(false); 408 private final AtomicBoolean mRegisteredForSatelliteRegistrationFailure = 409 new AtomicBoolean(false); 410 private final AtomicBoolean mRegisteredForTerrestrialNetworkAvailableChanged = 411 new AtomicBoolean(false); 412 private final AtomicBoolean mRegisteredForSatelliteCommunicationAccessStateChanged = 413 new AtomicBoolean(false); 414 /** 415 * Map key: subId, value: callback to get error code of the provision request. 416 */ 417 private final ConcurrentHashMap<Integer, Consumer<Integer>> mSatelliteProvisionCallbacks = 418 new ConcurrentHashMap<>(); 419 420 /** 421 * Map key: binder of the callback, value: callback to receive provision state changed events. 422 */ 423 private final ConcurrentHashMap<IBinder, ISatelliteProvisionStateCallback> 424 mSatelliteProvisionStateChangedListeners = new ConcurrentHashMap<>(); 425 /** 426 * Map key: binder of the callback, value: callback to receive non-terrestrial signal strength 427 * state changed events. 428 */ 429 private final ConcurrentHashMap<IBinder, INtnSignalStrengthCallback> 430 mNtnSignalStrengthChangedListeners = new ConcurrentHashMap<>(); 431 /** 432 * Map key: binder of the callback, value: callback to receive satellite capabilities changed 433 * events. 434 */ 435 private final ConcurrentHashMap<IBinder, ISatelliteCapabilitiesCallback> 436 mSatelliteCapabilitiesChangedListeners = new ConcurrentHashMap<>(); 437 /** 438 * Map key: binder of the callback, value: callback to receive supported state changed events. 439 */ 440 private final ConcurrentHashMap<IBinder, IBooleanConsumer> 441 mSatelliteSupportedStateChangedListeners = new ConcurrentHashMap<>(); 442 443 /** 444 * Map key: binder of the callback, value: callback to satellite registration failure 445 */ 446 private final ConcurrentHashMap<IBinder, ISatelliteModemStateCallback> 447 mSatelliteRegistrationFailureListeners = new ConcurrentHashMap<>(); 448 /** 449 * Map key: binder of the callback, value: callback to receive terrestrial network 450 * available changed 451 */ 452 private final ConcurrentHashMap<IBinder, ISatelliteModemStateCallback> 453 mTerrestrialNetworkAvailableChangedListeners = new ConcurrentHashMap<>(); 454 /** 455 * Map key: binder of the callback, value: callback to receive selected NB IOT satellite 456 * subscription changed 457 */ 458 private final ConcurrentHashMap<IBinder, ISelectedNbIotSatelliteSubscriptionCallback> 459 mSelectedNbIotSatelliteSubscriptionChangedListeners = new ConcurrentHashMap<>(); 460 461 protected final Object mIsSatelliteSupportedLock = new Object(); 462 @GuardedBy("mIsSatelliteSupportedLock") 463 protected Boolean mIsSatelliteSupported = null; 464 private boolean mIsDemoModeEnabled = false; 465 private boolean mIsEmergency = false; 466 private final Object mIsSatelliteEnabledLock = new Object(); 467 @GuardedBy("mIsSatelliteEnabledLock") 468 private Boolean mIsSatelliteEnabled = null; 469 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 470 protected final Object mIsRadioOnLock = new Object(); 471 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 472 protected boolean mIsRadioOn; 473 @GuardedBy("mIsRadioOnLock") 474 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 475 protected boolean mRadioOffRequested = false; 476 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 477 protected final Object mDeviceProvisionLock = new Object(); 478 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 479 @GuardedBy("mDeviceProvisionLock") 480 protected Boolean mIsDeviceProvisioned = null; 481 @GuardedBy("mDeviceProvisionLock") 482 private Boolean mOverriddenIsSatelliteViaOemProvisioned = null; 483 private final Object mSatelliteCapabilitiesLock = new Object(); 484 @GuardedBy("mSatelliteCapabilitiesLock") 485 private SatelliteCapabilities mSatelliteCapabilities; 486 private final Object mNeedsSatellitePointingLock = new Object(); 487 @GuardedBy("mNeedsSatellitePointingLock") 488 private boolean mNeedsSatellitePointing = false; 489 private final Object mNtnSignalsStrengthLock = new Object(); 490 @GuardedBy("mNtnSignalsStrengthLock") 491 private NtnSignalStrength mNtnSignalStrength = 492 new NtnSignalStrength(NTN_SIGNAL_STRENGTH_NONE); 493 /** Key: subId, value: (key: PLMN, value: set of 494 * {@link android.telephony.NetworkRegistrationInfo.ServiceType}) 495 */ 496 @GuardedBy("mSupportedSatelliteServicesLock") 497 @NonNull private final Map<Integer, Map<String, Set<Integer>>> 498 mSatelliteServicesSupportedByCarriersFromConfig = new HashMap<>(); 499 @NonNull private final Object mSupportedSatelliteServicesLock = new Object(); 500 @NonNull private final List<String> mSatellitePlmnListFromOverlayConfig; 501 @NonNull private final CarrierConfigManager mCarrierConfigManager; 502 @NonNull private final CarrierConfigManager.CarrierConfigChangeListener 503 mCarrierConfigChangeListener; 504 @NonNull private final ConfigProviderAdaptor.Callback mConfigDataUpdatedCallback; 505 @NonNull private final Object mCarrierConfigArrayLock = new Object(); 506 @NonNull 507 private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener; 508 @GuardedBy("mCarrierConfigArrayLock") 509 @NonNull private final SparseArray<PersistableBundle> mCarrierConfigArray = new SparseArray<>(); 510 @GuardedBy("mIsSatelliteEnabledLock") 511 /** Key: Subscription ID, value: set of restriction reasons for satellite communication.*/ 512 @NonNull private final Map<Integer, Set<Integer>> mSatelliteAttachRestrictionForCarrierArray = 513 new HashMap<>(); 514 @GuardedBy("mIsSatelliteEnabledLock") 515 /** Key: Subscription ID, value: the actual satellite enabled state in the modem - 516 * {@code true} for enabled and {@code false} for disabled. */ 517 @NonNull private final Map<Integer, Boolean> mIsSatelliteAttachEnabledForCarrierArrayPerSub = 518 new HashMap<>(); 519 /** Key: subId, value: (key: Regional satellite config Id string, value: Integer 520 * arrays of earfcns in the corresponding regions.) 521 */ 522 @GuardedBy("mRegionalSatelliteEarfcnsLock") 523 @NonNull private final Map<Integer, Map<String, Set<Integer>>> 524 mRegionalSatelliteEarfcns = new HashMap<>(); 525 @NonNull private final Object mRegionalSatelliteEarfcnsLock = new Object(); 526 @NonNull private final FeatureFlags mFeatureFlags; 527 @NonNull private final Object mSatelliteConnectedLock = new Object(); 528 /** Key: Subscription ID; Value: Last satellite connected time */ 529 @GuardedBy("mSatelliteConnectedLock") 530 @NonNull private final SparseArray<Long> mLastSatelliteDisconnectedTimesMillis = 531 new SparseArray<>(); 532 /** 533 * Key: Subscription ID; Value: {@code true} if satellite was just connected, 534 * {@code false} otherwise. 535 */ 536 @GuardedBy("mSatelliteConnectedLock") 537 @NonNull private final SparseBooleanArray 538 mWasSatelliteConnectedViaCarrier = new SparseBooleanArray(); 539 540 @GuardedBy("mSatelliteConnectedLock") 541 @NonNull private final SparseBooleanArray mLastNotifiedNtnMode = new SparseBooleanArray(); 542 543 @GuardedBy("mSatelliteConnectedLock") 544 @NonNull private final SparseBooleanArray mInitialized = new SparseBooleanArray(); 545 546 /** 547 * Boolean set to {@code true} when device is eligible to connect to carrier roaming 548 * non-terrestrial network else set to {@code false}. 549 */ 550 @GuardedBy("mSatellitePhoneLock") 551 private Boolean mLastNotifiedNtnEligibility = null; 552 @GuardedBy("mSatellitePhoneLock") 553 private boolean mCheckingAccessRestrictionInProgress = false; 554 555 @GuardedBy("mSatelliteConnectedLock") 556 @NonNull private final Map<Integer, CarrierRoamingSatelliteSessionStats> 557 mCarrierRoamingSatelliteSessionStatsMap = new HashMap<>(); 558 559 /** 560 * Key: Subscription ID; Value: set of 561 * {@link android.telephony.NetworkRegistrationInfo.ServiceType} 562 */ 563 @GuardedBy("mSatelliteConnectedLock") 564 @NonNull private final Map<Integer, List<Integer>> 565 mSatModeCapabilitiesForCarrierRoaming = new HashMap<>(); 566 567 @GuardedBy("mSatelliteConnectedLock") 568 private SparseArray<NtnSignalStrength> mLastNotifiedCarrierRoamingNtnSignalStrength = 569 new SparseArray<>(); 570 571 /** 572 * This is used for testing only. When mEnforcedEmergencyCallToSatelliteHandoverType is valid, 573 * Telephony will ignore the IMS registration status and cellular availability, and always send 574 * the connection event EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer. 575 */ 576 private int mEnforcedEmergencyCallToSatelliteHandoverType = 577 INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE; 578 private int mDelayInSendingEventDisplayEmergencyMessage = 0; 579 @NonNull private SharedPreferences mSharedPreferences = null; 580 581 @Nullable private PersistentLogger mPersistentLogger = null; 582 583 /** 584 * Key : Subscription ID, Value: {@code true} if the EntitlementStatus is enabled, 585 * {@code false} otherwise. 586 */ 587 @GuardedBy("mSupportedSatelliteServicesLock") 588 private SparseBooleanArray mSatelliteEntitlementStatusPerCarrier = new SparseBooleanArray(); 589 /** Key Subscription ID, value : PLMN allowed list from entitlement. */ 590 @GuardedBy("mSupportedSatelliteServicesLock") 591 private SparseArray<List<String>> mEntitlementPlmnListPerCarrier = new SparseArray<>(); 592 /** Key Subscription ID, value : PLMN barred list from entitlement. */ 593 @GuardedBy("mSupportedSatelliteServicesLock") 594 private SparseArray<List<String>> mEntitlementBarredPlmnListPerCarrier = new SparseArray<>(); 595 /** 596 * Key : Subscription ID, Value : If there is an entitlementPlmnList, use it. Otherwise, use the 597 * carrierPlmnList. */ 598 @GuardedBy("mSupportedSatelliteServicesLock") 599 private final SparseArray<List<String>> mMergedPlmnListPerCarrier = new SparseArray<>(); 600 /** Key Subscription ID, value : map to plmn info with related data plan. */ 601 @GuardedBy("mSupportedSatelliteServicesLock") 602 SparseArray<Map<String, Integer>> mEntitlementDataPlanMapPerCarrier = new SparseArray<>(); 603 /** Key Subscription ID, value : map to plmn info with related service type. */ 604 @GuardedBy("mSupportedSatelliteServicesLock") 605 SparseArray<Map<String, List<Integer>>> mEntitlementServiceTypeMapPerCarrier = 606 new SparseArray<>(); 607 /** Key Subscription ID, value : map to plmn info with related service policy for data service */ 608 @GuardedBy("mSupportedSatelliteServicesLock") 609 SparseArray<Map<String, Integer>> mEntitlementDataServicePolicyMapPerCarrier = 610 new SparseArray<>(); 611 /** Key Subscription ID, value : map to plmn info with related service policy for voice service */ 612 @GuardedBy("mSupportedSatelliteServicesLock") 613 SparseArray<Map<String, Integer>> mEntitlementVoiceServicePolicyMapPerCarrier = 614 new SparseArray<>(); 615 private static AtomicLong sNextSatelliteEnableRequestId = new AtomicLong(0); 616 private static AtomicLong sNextSystemSelectionChannelsUpdateRequestId = new AtomicLong(0); 617 // key : subscriberId, value : provisioned or not. 618 @GuardedBy("mSatelliteTokenProvisionedLock") 619 private Map<String, Boolean> mProvisionedSubscriberId = new HashMap<>(); 620 // key : subscriberId, value : subId 621 @GuardedBy("mSatelliteTokenProvisionedLock") 622 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 623 protected Map<String, Integer> mSubscriberIdPerSub = new HashMap<>(); 624 // key : priority, low value is high, value : List<SubscriptionInfo> 625 @GuardedBy("mSatelliteTokenProvisionedLock") 626 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 627 protected TreeMap<Integer, List<SubscriptionInfo>> mSubsInfoListPerPriority = new TreeMap<>(); 628 // List of subscriber information and status at the time of last evaluation 629 @GuardedBy("mSatelliteTokenProvisionedLock") 630 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 631 private List<SatelliteSubscriberProvisionStatus> mLastEvaluatedSubscriberProvisionStatus = 632 new ArrayList<>(); 633 // The ID of the satellite subscription that has highest priority and is provisioned. 634 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 635 protected int mSelectedSatelliteSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 636 // The last ICC ID that framework configured to modem. 637 @GuardedBy("mSatelliteTokenProvisionedLock") 638 private String mLastConfiguredIccId; 639 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 640 @NonNull protected final Object mSatelliteTokenProvisionedLock = new Object(); 641 private long mWaitTimeForSatelliteEnablingResponse; 642 private long mDemoPointingAlignedDurationMillis; 643 private long mDemoPointingNotAlignedDurationMillis; 644 private long mEvaluateEsosProfilesPrioritizationDurationMillis; 645 private final Object mLock = new Object(); 646 @GuardedBy("mLock") 647 private long mLastEmergencyCallTime; 648 private long mSatelliteEmergencyModeDurationMillis; 649 private static final int DEFAULT_SATELLITE_EMERGENCY_MODE_DURATION_SECONDS = 300; 650 private AlertDialog mNetworkSelectionModeAutoDialog = null; 651 652 /** Key used to read/write satellite system notification done in shared preferences. */ 653 private static final String SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY = 654 "satellite_system_notification_done_key"; 655 private static final String SATELLITE_SYSTEM_NOTIFICATION_TIME = 656 "satellite_system_notification_time"; 657 // The notification tag used when showing a notification. The combination of notification tag 658 // and notification id should be unique within the phone app. 659 private static final String NOTIFICATION_TAG = "SatelliteController"; 660 private static final int NOTIFICATION_ID = 1; 661 private static final String NOTIFICATION_CHANNEL = "satelliteChannel"; 662 private static final String NOTIFICATION_CHANNEL_ID = "satellite"; 663 664 private final RegistrantList mSatelliteConfigUpdateChangedRegistrants = new RegistrantList(); 665 private final RegistrantList mSatelliteSubIdChangedRegistrants = new RegistrantList(); 666 private final BTWifiNFCStateReceiver mBTWifiNFCSateReceiver; 667 private final UwbAdapterStateCallback mUwbAdapterStateCallback; 668 private final List<Integer> mCtsSatelliteAccessAllowedSubIds = new ArrayList<>(); 669 670 private long mSessionStartTimeStamp; 671 private long mSessionProcessingTimeStamp; 672 673 // Variable for backup and restore device's screen rotation settings. 674 private String mDeviceRotationLockToBackupAndRestore = null; 675 // This is used for testing only. Context#getSystemService is a final API and cannot be 676 // mocked. Using this to inject a mock SubscriptionManager to work around this limitation. 677 private SubscriptionManager mInjectSubscriptionManager = null; 678 679 private final Object mIsWifiConnectedLock = new Object(); 680 @GuardedBy("mIsWifiConnectedLock") 681 private boolean mIsWifiConnected = false; 682 private boolean mHasSentBroadcast = false; 683 // For satellite CTS test which to configure intent component with the necessary values. 684 private boolean mChangeIntentComponent = false; 685 private String mConfigSatelliteGatewayServicePackage = ""; 686 private String mConfigSatelliteCarrierRoamingEsosProvisionedClass = ""; 687 688 private boolean mIsNotificationShowing = false; 689 private static final String OPEN_MESSAGE_BUTTON = "open_message_button"; 690 private static final String HOW_IT_WORKS_BUTTON = "how_it_works_button"; 691 private static final String ACTION_NOTIFICATION_CLICK = "action_notification_click"; 692 private static final String ACTION_NOTIFICATION_DISMISS = "action_notification_dismiss"; 693 private AtomicBoolean mOverrideNtnEligibility; 694 private String mDefaultSmsPackageName = ""; 695 private String mSatelliteGatewayServicePackageName = ""; 696 private Boolean mOverriddenDisableSatelliteWhileEnableInProgressSupported = null; 697 698 private final Object mNtnSmsSupportedByMessagesAppLock = new Object(); 699 @GuardedBy("mNtnSmsSupportedByMessagesAppLock") 700 private Boolean mNtnSmsSupportedByMessagesApp = null; 701 702 private final Object mCarrierRoamingNtnAllSatellitePlmnSetLock = new Object(); 703 @GuardedBy("mCarrierRoamingNtnAllSatellitePlmnSetLock") 704 private Set<String> mCarrierRoamingNtnAllSatellitePlmnSet = null; 705 706 private final Object mSatelliteModemStateLock = new Object(); 707 @GuardedBy("mSatelliteModemStateLock") 708 @SatelliteManager.SatelliteModemState 709 private int mSatelliteModemState = SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN; 710 711 // Data Plan types at entitlement for the plmn allowed 712 public static final int SATELLITE_DATA_PLAN_METERED = 0; 713 public static final int SATELLITE_DATA_PLAN_UNMETERED = 1; 714 @IntDef(prefix = {"SATELLITE_DATA_PLAN_"}, value = { 715 SATELLITE_DATA_PLAN_METERED, 716 SATELLITE_DATA_PLAN_UNMETERED, 717 }) 718 @Retention(RetentionPolicy.SOURCE) 719 public @interface SatelliteDataPlan {} 720 private BroadcastReceiver 721 mDefaultSmsSubscriptionChangedBroadcastReceiver = new BroadcastReceiver() { 722 @Override 723 public void onReceive(Context context, Intent intent) { 724 if (intent.getAction().equals( 725 SubscriptionManager.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED)) { 726 plogd("Default SMS subscription changed"); 727 sendRequestAsync(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION, null, null); 728 } 729 } 730 }; 731 732 private BroadcastReceiver mPackageStateChangedReceiver = new BroadcastReceiver() { 733 @Override 734 public void onReceive(Context context, Intent intent) { 735 mDefaultSmsPackageName = Telephony.Sms.getDefaultSmsPackage(mContext); 736 mSatelliteGatewayServicePackageName = getConfigSatelliteGatewayServicePackage(); 737 String schemeSpecificPart = intent.getData().getSchemeSpecificPart(); 738 plogd("packageStateChanged: " + intent.getData().toString() 739 + " DefaultSmsPackageName:" + mDefaultSmsPackageName); 740 741 if (!schemeSpecificPart.equals(mSatelliteGatewayServicePackageName) 742 && !schemeSpecificPart.equals(mDefaultSmsPackageName)) { 743 plogv("Neither SMS or SatelliteGateway package"); 744 return; 745 } 746 int[] activeSubIds = mSubscriptionManagerService.getActiveSubIdList(true); 747 if (activeSubIds != null) { 748 for (int activeSubId : activeSubIds) { 749 plogd("mPackageStateChangedReceiver: activeSubId= " + activeSubId); 750 handleCarrierRoamingNtnAvailableServicesChanged(activeSubId); 751 } 752 } else { 753 ploge("mPackageStateChangedReceiver: activeSubIds is null"); 754 } 755 } 756 }; 757 758 protected BroadcastReceiver mLocationServiceStateChangedReceiver = new BroadcastReceiver() { 759 @Override 760 public void onReceive(Context context, Intent intent) { 761 // Check whether user has turned on/off location manager from settings menu 762 if (intent.getAction().equals(LocationManager.MODE_CHANGED_ACTION)) { 763 plogd("mLocationServiceStateChangedReceiver"); 764 sendRequestAsync(CMD_LOCATION_SERVICE_STATE_CHANGED, null, null); 765 } 766 } 767 }; 768 769 // List of device states returned from DeviceStateManager to determine if running on a foldable 770 // device. 771 private List<DeviceState> mDeviceStates = new ArrayList(); 772 773 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 774 protected final Object mSatelliteAccessConfigLock = new Object(); 775 @GuardedBy("mSatelliteAccessConfigLock") 776 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 777 protected List<Integer> mCurrentLocationTagIds = new ArrayList(); 778 @GuardedBy("mSatelliteAccessConfigLock") 779 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 780 protected boolean mSatelliteAccessAllowed = false; 781 782 public static final int RESULT_RECEIVER_COUNT_ANOMALY_THRESHOLD = 500; 783 protected final Object mResultReceiverTotalCountLock = new Object(); 784 @GuardedBy("mResultReceiverTotalCountLock") 785 protected int mResultReceiverTotalCount; 786 @GuardedBy("mResultReceiverTotalCountLock") 787 protected HashMap<String, Integer> mResultReceiverCountPerMethodMap = new HashMap<>(); 788 789 // Satellite anomaly uuid -- ResultReceiver count threshold exceeded 790 private final UUID mAnomalyUnexpectedResultReceiverCountUUID = 791 UUID.fromString("e268f22d-9bba-4d27-b76a-1c7f5b42e241"); 792 generateAnomalyUnexpectedResultReceiverCountUUID(int error, int errorCode)793 private UUID generateAnomalyUnexpectedResultReceiverCountUUID(int error, int errorCode) { 794 long lerror = error; 795 long lerrorCode = errorCode; 796 return new UUID(mAnomalyUnexpectedResultReceiverCountUUID.getMostSignificantBits(), 797 mAnomalyUnexpectedResultReceiverCountUUID.getLeastSignificantBits() 798 + ((lerrorCode << 32) + lerror)); 799 } 800 801 /** 802 * Increments the ResultReceiver count and logs the caller information. 803 * If the count exceeds the threshold, it reports an anomaly via AnomalyReporter. 804 * 805 * @param caller The caller information that created the ResultReceiver 806 * (e.g., class name and method name) 807 */ incrementResultReceiverCount(String caller)808 public void incrementResultReceiverCount(String caller) { 809 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 810 synchronized (mResultReceiverTotalCountLock) { 811 mResultReceiverTotalCount++; 812 logd("[incrementResultReceiverCount] : " + caller 813 + " | ResultReceiver total count= " + mResultReceiverTotalCount); 814 mResultReceiverCountPerMethodMap.compute(caller, 815 (k, v) -> v == null ? 1 : v + 1); 816 817 if (mResultReceiverTotalCount > RESULT_RECEIVER_COUNT_ANOMALY_THRESHOLD) { 818 loge("[mResultReceiverTotalCount] is exceeds limits : " 819 + mResultReceiverTotalCount); 820 loge("[incrementResultReceiverCount] mResultReceiverCountPerMethodMap is " 821 + mResultReceiverCountPerMethodMap); 822 AnomalyReporter.reportAnomaly( 823 generateAnomalyUnexpectedResultReceiverCountUUID(0, 0), 824 "Satellite ResultReceiver total count= " 825 + mResultReceiverTotalCount + " exceeds limit."); 826 } 827 } 828 } else { 829 logd("[incrementResultReceiverCount]: carrierRoamingNbIotNtn is not enabled"); 830 } 831 } 832 833 /** 834 * Decrements the ResultReceiver count and logs the caller information. 835 * Prevents the count from going below zero. 836 * 837 * @param caller The caller information that released the ResultReceiver 838 * (e.g., class name and method name) 839 */ decrementResultReceiverCount(String caller)840 public void decrementResultReceiverCount(String caller) { 841 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 842 synchronized (mResultReceiverTotalCountLock) { 843 if (mResultReceiverTotalCount > 0) { 844 mResultReceiverTotalCount--; 845 } 846 logd("[decrementResultReceiverCount] : " + caller 847 + " | ResultReceiver total count=" + mResultReceiverTotalCount); 848 mResultReceiverCountPerMethodMap.computeIfPresent(caller, 849 (k, v) -> v > 0 ? v - 1 : v); 850 } 851 } else { 852 logd("[decrementResultReceiverCount]: carrierRoamingNbIotNtn is not enabled"); 853 } 854 } 855 856 /** 857 * @return The singleton instance of SatelliteController. 858 */ getInstance()859 public static SatelliteController getInstance() { 860 if (sInstance == null) { 861 loge("SatelliteController was not yet initialized."); 862 } 863 return sInstance; 864 } 865 866 /** 867 * Create the SatelliteController singleton instance. 868 * @param context The Context to use to create the SatelliteController. 869 * @param featureFlags The feature flag. 870 */ make(@onNull Context context, @NonNull FeatureFlags featureFlags)871 public static void make(@NonNull Context context, @NonNull FeatureFlags featureFlags) { 872 if (sInstance == null) { 873 if (featureFlags.threadShred()) { 874 sInstance = new SatelliteController( 875 context, WorkerThread.get().getLooper(), featureFlags); 876 } else { 877 HandlerThread satelliteThread = new HandlerThread(TAG); 878 satelliteThread.start(); 879 sInstance = new SatelliteController( 880 context, satelliteThread.getLooper(), featureFlags); 881 } 882 } 883 } 884 885 /** 886 * Create a SatelliteController to act as a backend service of 887 * {@link android.telephony.satellite.SatelliteManager} 888 * 889 * @param context The Context for the SatelliteController. 890 * @param looper The looper for the handler. It does not run on main thread. 891 * @param featureFlags The feature flag. 892 */ 893 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) SatelliteController( @onNull Context context, @NonNull Looper looper, @NonNull FeatureFlags featureFlags)894 public SatelliteController( 895 @NonNull Context context, @NonNull Looper looper, @NonNull FeatureFlags featureFlags) { 896 super(looper); 897 898 mPersistentLogger = SatelliteServiceUtils.getPersistentLogger(context); 899 mContext = context; 900 mFeatureFlags = featureFlags; 901 Phone phone = SatelliteServiceUtils.getPhone(); 902 synchronized (mSatellitePhoneLock) { 903 mSatellitePhone = phone; 904 } 905 mCi = phone.mCi; 906 mDSM = phone.getDeviceStateMonitor(); 907 // Create the SatelliteModemInterface singleton, which is used to manage connections 908 // to the satellite service and HAL interface. 909 mSatelliteModemInterface = SatelliteModemInterface.make( 910 mContext, this, mFeatureFlags); 911 mCountryDetector = TelephonyCountryDetector.getInstance(context, mFeatureFlags); 912 mCountryDetector.registerForWifiConnectivityStateChanged(this, 913 EVENT_WIFI_CONNECTIVITY_STATE_CHANGED, null); 914 mTelecomManager = mContext.getSystemService(TelecomManager.class); 915 916 // Create the PointingUIController singleton, 917 // which is used to manage interactions with PointingUI app. 918 mPointingAppController = PointingAppController.make(mContext, mFeatureFlags); 919 920 // Create the SatelliteControllerMetrics to report controller metrics 921 // should be called before making DatagramController 922 mControllerMetricsStats = ControllerMetricsStats.make(mContext); 923 mProvisionMetricsStats = ProvisionMetricsStats.getOrCreateInstance(); 924 mSessionMetricsStats = SessionMetricsStats.getInstance(); 925 mCarrierRoamingSatelliteControllerStats = 926 CarrierRoamingSatelliteControllerStats.getOrCreateInstance(); 927 mSubscriptionManagerService = SubscriptionManagerService.getInstance(); 928 929 // Create the DatagramController singleton, 930 // which is used to send and receive satellite datagrams. 931 mDatagramController = DatagramController.make( 932 mContext, looper, mFeatureFlags, mPointingAppController); 933 934 mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null); 935 synchronized (mIsRadioOnLock) { 936 mIsRadioOn = phone.isRadioOn(); 937 } 938 939 registerForPendingDatagramCount(); 940 registerForSatelliteModemStateChanged(); 941 registerForServiceStateChanged(); 942 registerForSignalStrengthChanged(); 943 registerForSatelliteCommunicationAccessStateChanged(); 944 mContentResolver = mContext.getContentResolver(); 945 mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class); 946 947 mBTWifiNFCSateReceiver = new BTWifiNFCStateReceiver(); 948 mUwbAdapterStateCallback = new UwbAdapterStateCallback(); 949 initializeSatelliteModeRadios(); 950 951 ContentObserver satelliteModeRadiosContentObserver = new ContentObserver(this) { 952 @Override 953 public void onChange(boolean selfChange) { 954 initializeSatelliteModeRadios(); 955 } 956 }; 957 if (mContentResolver != null) { 958 mContentResolver.registerContentObserver( 959 Settings.Global.getUriFor(Settings.Global.SATELLITE_MODE_RADIOS), 960 false, satelliteModeRadiosContentObserver); 961 } 962 963 mSatellitePlmnListFromOverlayConfig = readSatellitePlmnsFromOverlayConfig(); 964 registerApplicationStateChanged(); 965 registerLocationServiceStateChanged(); 966 updateSupportedSatelliteServicesForActiveSubscriptions(); 967 mCarrierConfigChangeListener = 968 (slotIndex, subId, carrierId, specificCarrierId) -> 969 handleCarrierConfigChanged(slotIndex, subId, carrierId, specificCarrierId); 970 if (mCarrierConfigManager != null) { 971 mCarrierConfigManager.registerCarrierConfigChangeListener( 972 new HandlerExecutor(new Handler(looper)), mCarrierConfigChangeListener); 973 } 974 975 mConfigDataUpdatedCallback = new ConfigProviderAdaptor.Callback() { 976 @Override 977 public void onChanged(@Nullable ConfigParser config) { 978 SatelliteControllerHandlerRequest request = 979 new SatelliteControllerHandlerRequest(true, 980 SatelliteServiceUtils.getPhone()); 981 sendRequestAsync(EVENT_SATELLITE_CONFIG_DATA_UPDATED, request, null); 982 } 983 }; 984 TelephonyConfigUpdateInstallReceiver.getInstance() 985 .registerCallback(Executors.newSingleThreadExecutor(), mConfigDataUpdatedCallback); 986 987 mDSM.registerForSignalStrengthReportDecision(this, CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING, 988 null); 989 990 loadSatelliteSharedPreferences(); 991 if (mSharedPreferences != null) { 992 try { 993 synchronized (mNtnSmsSupportedByMessagesAppLock) { 994 mNtnSmsSupportedByMessagesApp = mSharedPreferences.getBoolean( 995 NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY, false); 996 } 997 998 synchronized (mCarrierRoamingNtnAllSatellitePlmnSetLock) { 999 mCarrierRoamingNtnAllSatellitePlmnSet = mSharedPreferences.getStringSet( 1000 CARRIER_ROAMING_NTN_ALL_SATELLITE_PLMN_SET_KEY, new HashSet<>()); 1001 } 1002 } catch (Exception ex) { 1003 plogd("SatelliteController constructor: " 1004 + "cannot get default shared preferences. e" + ex); 1005 } 1006 } 1007 1008 mWaitTimeForSatelliteEnablingResponse = getWaitForSatelliteEnablingResponseTimeoutMillis(); 1009 mDemoPointingAlignedDurationMillis = getDemoPointingAlignedDurationMillisFromResources(); 1010 mDemoPointingNotAlignedDurationMillis = 1011 getDemoPointingNotAlignedDurationMillisFromResources(); 1012 mSatelliteEmergencyModeDurationMillis = 1013 getSatelliteEmergencyModeDurationFromOverlayConfig(context); 1014 mEvaluateEsosProfilesPrioritizationDurationMillis = 1015 getEvaluateEsosProfilesPrioritizationDurationMillis(); 1016 sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION), 1017 mEvaluateEsosProfilesPrioritizationDurationMillis); 1018 1019 SubscriptionManager subscriptionManager = mContext.getSystemService( 1020 SubscriptionManager.class); 1021 mSubscriptionsChangedListener = new SatelliteSubscriptionsChangedListener(); 1022 if (subscriptionManager != null) { 1023 subscriptionManager.addOnSubscriptionsChangedListener( 1024 new HandlerExecutor(new Handler(looper)), mSubscriptionsChangedListener); 1025 } 1026 registerDefaultSmsSubscriptionChangedBroadcastReceiver(); 1027 updateSatelliteProvisionedStatePerSubscriberId(); 1028 if (android.hardware.devicestate.feature.flags.Flags.deviceStatePropertyMigration()) { 1029 mDeviceStates = getSupportedDeviceStates(); 1030 } 1031 1032 mSatelliteOptimizedApplicationsTracker = new SatelliteOptimizedApplicationsTracker( 1033 getLooper(), mContext 1034 ); 1035 1036 for (Phone phoneToSendRequest : PhoneFactory.getPhones()) { 1037 sendRequestAsync(CMD_GET_SATELLITE_ENABLED_FOR_CARRIER, null, phoneToSendRequest); 1038 } 1039 1040 logd("Satellite Tracker is created"); 1041 } 1042 1043 class SatelliteSubscriptionsChangedListener 1044 extends SubscriptionManager.OnSubscriptionsChangedListener { 1045 1046 /** 1047 * Callback invoked when there is any change to any SubscriptionInfo. 1048 */ 1049 @Override onSubscriptionsChanged()1050 public void onSubscriptionsChanged() { 1051 handleSubscriptionsChanged(); 1052 } 1053 } 1054 1055 /** 1056 * Register a callback to get a updated satellite config data. 1057 * @param h Handler to notify 1058 * @param what msg.what when the message is delivered 1059 * @param obj AsyncResult.userObj when the message is delivered 1060 */ registerForConfigUpdateChanged(Handler h, int what, Object obj)1061 public void registerForConfigUpdateChanged(Handler h, int what, Object obj) { 1062 Registrant r = new Registrant(h, what, obj); 1063 mSatelliteConfigUpdateChangedRegistrants.add(r); 1064 } 1065 1066 /** 1067 * Unregister a callback to get a updated satellite config data. 1068 * @param h Handler to notify 1069 */ unregisterForConfigUpdateChanged(Handler h)1070 public void unregisterForConfigUpdateChanged(Handler h) { 1071 mSatelliteConfigUpdateChangedRegistrants.remove(h); 1072 } 1073 1074 /** 1075 * Register a callback to change the satelliteSubId. 1076 * @param h Handler to notify 1077 * @param what msg.what when the message is delivered 1078 * @param obj AsyncResult.userObj when the message is delivered 1079 */ registerForSatelliteSubIdChanged(Handler h, int what, Object obj)1080 public void registerForSatelliteSubIdChanged(Handler h, int what, Object obj) { 1081 Registrant r = new Registrant(h, what, obj); 1082 mSatelliteSubIdChangedRegistrants.add(r); 1083 } 1084 1085 /** 1086 * Unregister a callback to get a updated satellite config data. 1087 * @param h Handler to notify 1088 */ unregisterForSatelliteSubIdChanged(Handler h)1089 public void unregisterForSatelliteSubIdChanged(Handler h) { 1090 mSatelliteSubIdChangedRegistrants.remove(h); 1091 } 1092 /** 1093 * Get satelliteConfig from SatelliteConfigParser 1094 */ getSatelliteConfig()1095 public SatelliteConfig getSatelliteConfig() { 1096 SatelliteConfigParser satelliteConfigParser = getSatelliteConfigParser(); 1097 if (satelliteConfigParser == null) { 1098 Log.d(TAG, "satelliteConfigParser is not ready"); 1099 return null; 1100 } 1101 return satelliteConfigParser.getConfig(); 1102 } 1103 1104 /** 1105 * This API should be used by only CTS/unit tests to reset the telephony configs set through 1106 * config updater 1107 */ 1108 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) cleanUpTelephonyConfigs()1109 public void cleanUpTelephonyConfigs() { 1110 TelephonyConfigUpdateInstallReceiver.getInstance().cleanUpTelephonyConfigs(); 1111 } 1112 1113 /** 1114 * Get SatelliteConfigParser from TelephonyConfigUpdateInstallReceiver 1115 */ 1116 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) getSatelliteConfigParser()1117 public SatelliteConfigParser getSatelliteConfigParser() { 1118 return (SatelliteConfigParser) TelephonyConfigUpdateInstallReceiver 1119 .getInstance().getConfigParser(DOMAIN_SATELLITE); 1120 } 1121 1122 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) initializeSatelliteModeRadios()1123 protected void initializeSatelliteModeRadios() { 1124 if (mContentResolver != null) { 1125 IntentFilter radioStateIntentFilter = new IntentFilter(); 1126 1127 synchronized (mRadioStateLock) { 1128 // Initialize radio states to default value 1129 mDisableBTOnSatelliteEnabled = false; 1130 mDisableNFCOnSatelliteEnabled = false; 1131 mDisableWifiOnSatelliteEnabled = false; 1132 mDisableUWBOnSatelliteEnabled = false; 1133 1134 mBTStateEnabled = false; 1135 mNfcStateEnabled = false; 1136 mWifiStateEnabled = false; 1137 mUwbStateEnabled = false; 1138 1139 // Read satellite mode radios from settings 1140 String satelliteModeRadios = Settings.Global.getString(mContentResolver, 1141 Settings.Global.SATELLITE_MODE_RADIOS); 1142 if (satelliteModeRadios == null) { 1143 ploge("initializeSatelliteModeRadios: satelliteModeRadios is null"); 1144 return; 1145 } 1146 plogd("Radios To be checked when satellite is on: " + satelliteModeRadios); 1147 1148 if (satelliteModeRadios.contains(Settings.Global.RADIO_BLUETOOTH)) { 1149 BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 1150 if (bluetoothAdapter != null) { 1151 mDisableBTOnSatelliteEnabled = true; 1152 mBTStateEnabled = bluetoothAdapter.isEnabled(); 1153 radioStateIntentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); 1154 } 1155 } 1156 1157 if (satelliteModeRadios.contains(Settings.Global.RADIO_NFC)) { 1158 Context applicationContext = mContext.getApplicationContext(); 1159 NfcAdapter nfcAdapter = null; 1160 if (applicationContext != null) { 1161 nfcAdapter = NfcAdapter.getDefaultAdapter(mContext.getApplicationContext()); 1162 } 1163 if (nfcAdapter != null) { 1164 mDisableNFCOnSatelliteEnabled = true; 1165 mNfcStateEnabled = nfcAdapter.isEnabled(); 1166 radioStateIntentFilter.addAction(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 1167 } 1168 } 1169 1170 if (satelliteModeRadios.contains(Settings.Global.RADIO_WIFI)) { 1171 WifiManager wifiManager = mContext.getSystemService(WifiManager.class); 1172 if (wifiManager != null) { 1173 mDisableWifiOnSatelliteEnabled = true; 1174 mWifiStateEnabled = wifiManager.isWifiEnabled(); 1175 radioStateIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 1176 } 1177 } 1178 1179 try { 1180 // Unregister receiver before registering it. 1181 mContext.unregisterReceiver(mBTWifiNFCSateReceiver); 1182 } catch (IllegalArgumentException e) { 1183 plogd("initializeSatelliteModeRadios: unregisterReceiver, e=" + e); 1184 } 1185 mContext.registerReceiver(mBTWifiNFCSateReceiver, radioStateIntentFilter); 1186 1187 if (satelliteModeRadios.contains(Settings.Global.RADIO_UWB)) { 1188 UwbManager uwbManager = mContext.getSystemService(UwbManager.class); 1189 if (uwbManager != null) { 1190 mDisableUWBOnSatelliteEnabled = true; 1191 mUwbStateEnabled = uwbManager.isUwbEnabled(); 1192 final long identity = Binder.clearCallingIdentity(); 1193 try { 1194 // Unregister callback before registering it. 1195 uwbManager.unregisterAdapterStateCallback(mUwbAdapterStateCallback); 1196 uwbManager.registerAdapterStateCallback(mContext.getMainExecutor(), 1197 mUwbAdapterStateCallback); 1198 } finally { 1199 Binder.restoreCallingIdentity(identity); 1200 } 1201 } 1202 } 1203 1204 plogd("mDisableBTOnSatelliteEnabled: " + mDisableBTOnSatelliteEnabled 1205 + " mDisableNFCOnSatelliteEnabled: " + mDisableNFCOnSatelliteEnabled 1206 + " mDisableWifiOnSatelliteEnabled: " + mDisableWifiOnSatelliteEnabled 1207 + " mDisableUWBOnSatelliteEnabled: " + mDisableUWBOnSatelliteEnabled); 1208 1209 plogd("mBTStateEnabled: " + mBTStateEnabled 1210 + " mNfcStateEnabled: " + mNfcStateEnabled 1211 + " mWifiStateEnabled: " + mWifiStateEnabled 1212 + " mUwbStateEnabled: " + mUwbStateEnabled); 1213 } 1214 } 1215 } 1216 1217 protected class UwbAdapterStateCallback implements UwbManager.AdapterStateCallback { 1218 toString(int state)1219 public String toString(int state) { 1220 switch (state) { 1221 case UwbManager.AdapterStateCallback.STATE_DISABLED: 1222 return "Disabled"; 1223 1224 case UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE: 1225 return "Inactive"; 1226 1227 case UwbManager.AdapterStateCallback.STATE_ENABLED_ACTIVE: 1228 return "Active"; 1229 1230 default: 1231 return ""; 1232 } 1233 } 1234 1235 @Override onStateChanged(int state, int reason)1236 public void onStateChanged(int state, int reason) { 1237 plogd("UwbAdapterStateCallback#onStateChanged() called, state = " + toString(state)); 1238 plogd("Adapter state changed reason " + String.valueOf(reason)); 1239 if (state == UwbManager.AdapterStateCallback.STATE_DISABLED) { 1240 setUwbEnabledState(false); 1241 evaluateToSendSatelliteEnabledSuccess(); 1242 } else { 1243 setUwbEnabledState(true); 1244 } 1245 plogd("mUwbStateEnabled: " + getUwbEnabledState()); 1246 } 1247 } 1248 1249 protected class BTWifiNFCStateReceiver extends BroadcastReceiver { 1250 @Override onReceive(Context context, Intent intent)1251 public void onReceive(Context context, Intent intent) { 1252 final String action = intent.getAction(); 1253 if (action == null) { 1254 plogd("BTWifiNFCStateReceiver NULL action for intent " + intent); 1255 return; 1256 } 1257 1258 switch (action) { 1259 case BluetoothAdapter.ACTION_STATE_CHANGED: 1260 int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 1261 BluetoothAdapter.ERROR); 1262 boolean currentBTStateEnabled = getBTEnabledState(); 1263 if (btState == BluetoothAdapter.STATE_OFF) { 1264 setBTEnabledState(false); 1265 evaluateToSendSatelliteEnabledSuccess(); 1266 } else if (btState == BluetoothAdapter.STATE_ON) { 1267 setBTEnabledState(true); 1268 } 1269 1270 if (currentBTStateEnabled != getBTEnabledState()) { 1271 plogd("mBTStateEnabled=" + getBTEnabledState()); 1272 } 1273 break; 1274 1275 case NfcAdapter.ACTION_ADAPTER_STATE_CHANGED: 1276 int nfcState = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE, -1); 1277 boolean currentNfcStateEnabled = getNfcEnabledState(); 1278 if (nfcState == NfcAdapter.STATE_ON) { 1279 setNfcEnabledState(true); 1280 } else if (nfcState == NfcAdapter.STATE_OFF) { 1281 setNfcEnabledState(false); 1282 evaluateToSendSatelliteEnabledSuccess(); 1283 } 1284 1285 if (currentNfcStateEnabled != getNfcEnabledState()) { 1286 plogd("mNfcStateEnabled=" + getNfcEnabledState()); 1287 } 1288 break; 1289 1290 case WifiManager.WIFI_STATE_CHANGED_ACTION: 1291 int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 1292 WifiManager.WIFI_STATE_UNKNOWN); 1293 boolean currentWifiStateEnabled = getWifiEnabledState(); 1294 if (wifiState == WifiManager.WIFI_STATE_ENABLED) { 1295 setWifiEnabledState(true); 1296 } else if (wifiState == WifiManager.WIFI_STATE_DISABLED) { 1297 setWifiEnabledState(false); 1298 evaluateToSendSatelliteEnabledSuccess(); 1299 } 1300 1301 if (currentWifiStateEnabled != getWifiEnabledState()) { 1302 plogd("mWifiStateEnabled=" + getWifiEnabledState()); 1303 } 1304 break; 1305 default: 1306 break; 1307 } 1308 } 1309 } 1310 1311 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 1312 public static final class SatelliteControllerHandlerRequest { 1313 /** The argument to use for the request */ 1314 public @NonNull Object argument; 1315 /** The caller needs to specify the phone to be used for the request */ 1316 public @NonNull Phone phone; 1317 /** The result of the request that is run on the main thread */ 1318 public @Nullable Object result; 1319 SatelliteControllerHandlerRequest(Object argument, Phone phone)1320 public SatelliteControllerHandlerRequest(Object argument, Phone phone) { 1321 this.argument = argument; 1322 this.phone = phone; 1323 } 1324 } 1325 1326 private static final class RequestSatelliteEnabledArgument { 1327 public boolean enableSatellite; 1328 public boolean enableDemoMode; 1329 public boolean isEmergency; 1330 @NonNull public Consumer<Integer> callback; 1331 public long requestId; 1332 RequestSatelliteEnabledArgument(boolean enableSatellite, boolean enableDemoMode, boolean isEmergency, Consumer<Integer> callback)1333 RequestSatelliteEnabledArgument(boolean enableSatellite, boolean enableDemoMode, 1334 boolean isEmergency, Consumer<Integer> callback) { 1335 this.enableSatellite = enableSatellite; 1336 this.enableDemoMode = enableDemoMode; 1337 this.isEmergency = isEmergency; 1338 this.callback = callback; 1339 this.requestId = sNextSatelliteEnableRequestId.getAndUpdate( 1340 n -> ((n + 1) % Long.MAX_VALUE)); 1341 } 1342 } 1343 1344 private static final class RequestHandleSatelliteAttachRestrictionForCarrierArgument { 1345 public int subId; 1346 @SatelliteManager.SatelliteCommunicationRestrictionReason 1347 public int reason; 1348 @NonNull public Consumer<Integer> callback; 1349 RequestHandleSatelliteAttachRestrictionForCarrierArgument(int subId, @SatelliteManager.SatelliteCommunicationRestrictionReason int reason, Consumer<Integer> callback)1350 RequestHandleSatelliteAttachRestrictionForCarrierArgument(int subId, 1351 @SatelliteManager.SatelliteCommunicationRestrictionReason int reason, 1352 Consumer<Integer> callback) { 1353 this.subId = subId; 1354 this.reason = reason; 1355 this.callback = callback; 1356 } 1357 } 1358 1359 private static final class ProvisionSatelliteServiceArgument { 1360 @NonNull public String token; 1361 @NonNull public byte[] provisionData; 1362 @NonNull public Consumer<Integer> callback; 1363 public int subId; 1364 ProvisionSatelliteServiceArgument(String token, byte[] provisionData, Consumer<Integer> callback, int subId)1365 ProvisionSatelliteServiceArgument(String token, byte[] provisionData, 1366 Consumer<Integer> callback, int subId) { 1367 this.token = token; 1368 this.provisionData = provisionData; 1369 this.callback = callback; 1370 this.subId = subId; 1371 } 1372 } 1373 1374 private static final class UpdateSystemSelectionChannelsArgument { 1375 public @NonNull List<SystemSelectionSpecifier> systemSelectionSpecifiers; 1376 public @NonNull ResultReceiver result; 1377 public long requestId; 1378 UpdateSystemSelectionChannelsArgument( @onNull List<SystemSelectionSpecifier> systemSelectionSpecifiers, @NonNull ResultReceiver result)1379 UpdateSystemSelectionChannelsArgument( 1380 @NonNull List<SystemSelectionSpecifier> systemSelectionSpecifiers, 1381 @NonNull ResultReceiver result) { 1382 this.systemSelectionSpecifiers = systemSelectionSpecifiers; 1383 this.result = result; 1384 this.requestId = sNextSystemSelectionChannelsUpdateRequestId.getAndUpdate( 1385 n -> ((n + 1) % Long.MAX_VALUE)); 1386 } 1387 } 1388 1389 /** 1390 * Arguments to send to SatelliteTransmissionUpdate registrants 1391 */ 1392 public static final class SatelliteTransmissionUpdateArgument { 1393 @NonNull public Consumer<Integer> errorCallback; 1394 @NonNull public ISatelliteTransmissionUpdateCallback callback; 1395 public int subId; 1396 SatelliteTransmissionUpdateArgument(Consumer<Integer> errorCallback, ISatelliteTransmissionUpdateCallback callback, int subId)1397 SatelliteTransmissionUpdateArgument(Consumer<Integer> errorCallback, 1398 ISatelliteTransmissionUpdateCallback callback, int subId) { 1399 this.errorCallback = errorCallback; 1400 this.callback = callback; 1401 this.subId = subId; 1402 } 1403 } 1404 1405 @Override handleMessage(Message msg)1406 public void handleMessage(Message msg) { 1407 SatelliteControllerHandlerRequest request; 1408 Message onCompleted; 1409 AsyncResult ar; 1410 1411 switch(msg.what) { 1412 case CMD_START_SATELLITE_TRANSMISSION_UPDATES: { 1413 request = (SatelliteControllerHandlerRequest) msg.obj; 1414 onCompleted = 1415 obtainMessage(EVENT_START_SATELLITE_TRANSMISSION_UPDATES_DONE, request); 1416 mPointingAppController.startSatelliteTransmissionUpdates(onCompleted); 1417 break; 1418 } 1419 1420 case EVENT_START_SATELLITE_TRANSMISSION_UPDATES_DONE: { 1421 handleStartSatelliteTransmissionUpdatesDone((AsyncResult) msg.obj); 1422 break; 1423 } 1424 1425 case CMD_STOP_SATELLITE_TRANSMISSION_UPDATES: { 1426 request = (SatelliteControllerHandlerRequest) msg.obj; 1427 onCompleted = 1428 obtainMessage(EVENT_STOP_SATELLITE_TRANSMISSION_UPDATES_DONE, request); 1429 mPointingAppController.stopSatelliteTransmissionUpdates(onCompleted); 1430 break; 1431 } 1432 1433 case EVENT_STOP_SATELLITE_TRANSMISSION_UPDATES_DONE: { 1434 ar = (AsyncResult) msg.obj; 1435 request = (SatelliteControllerHandlerRequest) ar.userObj; 1436 int error = SatelliteServiceUtils.getSatelliteError(ar, 1437 "stopSatelliteTransmissionUpdates"); 1438 ((Consumer<Integer>) request.argument).accept(error); 1439 break; 1440 } 1441 1442 case CMD_PROVISION_SATELLITE_SERVICE: { 1443 request = (SatelliteControllerHandlerRequest) msg.obj; 1444 ProvisionSatelliteServiceArgument argument = 1445 (ProvisionSatelliteServiceArgument) request.argument; 1446 if (mSatelliteProvisionCallbacks.containsKey(argument.subId)) { 1447 argument.callback.accept( 1448 SatelliteManager.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS); 1449 notifyRequester(request); 1450 break; 1451 } 1452 mSatelliteProvisionCallbacks.put(argument.subId, argument.callback); 1453 // Log the current time for provision triggered 1454 mProvisionMetricsStats.setProvisioningStartTime(); 1455 Message provisionSatelliteServiceDoneEvent = this.obtainMessage( 1456 EVENT_PROVISION_SATELLITE_SERVICE_DONE, 1457 new AsyncResult(request, SATELLITE_RESULT_SUCCESS, null)); 1458 provisionSatelliteServiceDoneEvent.sendToTarget(); 1459 break; 1460 } 1461 1462 case EVENT_PROVISION_SATELLITE_SERVICE_DONE: { 1463 ar = (AsyncResult) msg.obj; 1464 request = (SatelliteControllerHandlerRequest) ar.userObj; 1465 int errorCode = SatelliteServiceUtils.getSatelliteError(ar, 1466 "provisionSatelliteService"); 1467 handleEventProvisionSatelliteServiceDone( 1468 (ProvisionSatelliteServiceArgument) request.argument, errorCode); 1469 notifyRequester(request); 1470 break; 1471 } 1472 1473 case CMD_DEPROVISION_SATELLITE_SERVICE: { 1474 request = (SatelliteControllerHandlerRequest) msg.obj; 1475 ProvisionSatelliteServiceArgument argument = 1476 (ProvisionSatelliteServiceArgument) request.argument; 1477 if (argument.callback != null) { 1478 mProvisionMetricsStats.setProvisioningStartTime(); 1479 } 1480 Message deprovisionSatelliteServiceDoneEvent = this.obtainMessage( 1481 EVENT_DEPROVISION_SATELLITE_SERVICE_DONE, 1482 new AsyncResult(request, SATELLITE_RESULT_SUCCESS, null)); 1483 deprovisionSatelliteServiceDoneEvent.sendToTarget(); 1484 break; 1485 } 1486 1487 case EVENT_DEPROVISION_SATELLITE_SERVICE_DONE: { 1488 ar = (AsyncResult) msg.obj; 1489 request = (SatelliteControllerHandlerRequest) ar.userObj; 1490 int errorCode = SatelliteServiceUtils.getSatelliteError(ar, 1491 "deprovisionSatelliteService"); 1492 handleEventDeprovisionSatelliteServiceDone( 1493 (ProvisionSatelliteServiceArgument) request.argument, errorCode); 1494 break; 1495 } 1496 1497 case CMD_SET_SATELLITE_ENABLED: { 1498 request = (SatelliteControllerHandlerRequest) msg.obj; 1499 handleSatelliteEnabled(request); 1500 break; 1501 } 1502 1503 case EVENT_SET_SATELLITE_ENABLED_DONE: { 1504 ar = (AsyncResult) msg.obj; 1505 request = (SatelliteControllerHandlerRequest) ar.userObj; 1506 RequestSatelliteEnabledArgument argument = 1507 (RequestSatelliteEnabledArgument) request.argument; 1508 int error = SatelliteServiceUtils.getSatelliteError(ar, "setSatelliteEnabled"); 1509 plogd("EVENT_SET_SATELLITE_ENABLED_DONE = " + error); 1510 1511 /* 1512 * The timer to wait for EVENT_SET_SATELLITE_ENABLED_DONE might have expired and 1513 * thus the request resources might have been cleaned up. 1514 */ 1515 if (!shouldProcessEventSetSatelliteEnabledDone(argument)) { 1516 plogw("The request ID=" + argument.requestId + ", enableSatellite=" 1517 + argument.enableSatellite + " was already processed"); 1518 return; 1519 } 1520 if (shouldStopWaitForEnableResponseTimer(argument)) { 1521 stopWaitForSatelliteEnablingResponseTimer(argument); 1522 } else { 1523 plogd("Still waiting for the OFF state from modem"); 1524 } 1525 1526 if (error == SATELLITE_RESULT_SUCCESS) { 1527 if (argument.enableSatellite) { 1528 synchronized (mSatelliteEnabledRequestLock) { 1529 mWaitingForRadioDisabled = true; 1530 setDemoModeEnabled(argument.enableDemoMode); 1531 } 1532 // TODO (b/361139260): Start a timer to wait for other radios off 1533 setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_TRUE); 1534 setSettingsKeyToAllowDeviceRotation(SATELLITE_MODE_ENABLED_TRUE); 1535 evaluateToSendSatelliteEnabledSuccess(); 1536 } else { 1537 // Unregister importance listener for PointingUI when satellite is disabled 1538 if (mNeedsSatellitePointing) { 1539 mPointingAppController.removeListenerForPointingUI(); 1540 } 1541 1542 if (!isWaitingForSatelliteModemOff()) { 1543 moveSatelliteToOffStateAndCleanUpResources(SATELLITE_RESULT_SUCCESS); 1544 } 1545 1546 synchronized (mSatelliteEnabledRequestLock) { 1547 mWaitingForDisableSatelliteModemResponse = false; 1548 } 1549 } 1550 // Request NTN signal strength report when satellite enabled or disabled done. 1551 mLatestRequestedStateForNtnSignalStrengthReport.set(argument.enableSatellite); 1552 updateNtnSignalStrengthReporting(argument.enableSatellite); 1553 } else { 1554 if (argument.enableSatellite) { 1555 /* Framework need to abort the enable attributes update request if any since 1556 * modem failed to enable satellite. 1557 */ 1558 abortSatelliteEnableAttributesUpdateRequest( 1559 SATELLITE_RESULT_REQUEST_ABORTED); 1560 resetSatelliteEnabledRequest(); 1561 } else { 1562 resetSatelliteDisabledRequest(); 1563 } 1564 notifyEnablementFailedToSatelliteSessionController(argument.enableSatellite); 1565 // If Satellite enable/disable request returned Error, no need to wait for radio 1566 argument.callback.accept(error); 1567 } 1568 if (argument.enableSatellite) { 1569 mSessionMetricsStats.resetSessionStatsShadowCounters(); 1570 mSessionMetricsStats.setInitializationResult(error) 1571 .setSatelliteTechnology(getSupportedNtnRadioTechnology()) 1572 .setInitializationProcessingTime( 1573 getElapsedRealtime() - mSessionProcessingTimeStamp) 1574 .setIsDemoMode(mIsDemoModeEnabled) 1575 .setCarrierId(getSatelliteCarrierId()) 1576 .setIsEmergency(argument.isEmergency); 1577 mSessionProcessingTimeStamp = 0; 1578 1579 if (error == SATELLITE_RESULT_SUCCESS) { 1580 mControllerMetricsStats.onSatelliteEnabled(); 1581 mControllerMetricsStats.reportServiceEnablementSuccessCount(); 1582 } else { 1583 mSessionMetricsStats.reportSessionMetrics(); 1584 mSessionStartTimeStamp = 0; 1585 mControllerMetricsStats.reportServiceEnablementFailCount(); 1586 } 1587 } else { 1588 mSessionMetricsStats.setTerminationResult(error) 1589 .setTerminationProcessingTime(getElapsedRealtime() 1590 - mSessionProcessingTimeStamp) 1591 .setSessionDurationSec(calculateSessionDurationTimeSec()) 1592 .reportSessionMetrics(); 1593 mSessionStartTimeStamp = 0; 1594 mSessionProcessingTimeStamp = 0; 1595 mControllerMetricsStats.onSatelliteDisabled(); 1596 handlePersistentLoggingOnSessionEnd(mIsEmergency); 1597 synchronized (mSatelliteEnabledRequestLock) { 1598 mWaitingForDisableSatelliteModemResponse = false; 1599 } 1600 } 1601 break; 1602 } 1603 1604 case EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT: { 1605 handleEventWaitForSatelliteEnablingResponseTimedOut( 1606 (RequestSatelliteEnabledArgument) msg.obj); 1607 break; 1608 } 1609 1610 case CMD_UPDATE_SATELLITE_ENABLE_ATTRIBUTES: { 1611 request = (SatelliteControllerHandlerRequest) msg.obj; 1612 RequestSatelliteEnabledArgument argument = 1613 (RequestSatelliteEnabledArgument) request.argument; 1614 1615 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 1616 plogd("UpdateEnableAttributes: carrierRoamingNbIotNtn flag is disabled"); 1617 sendErrorAndReportSessionMetrics( 1618 SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS, argument.callback); 1619 synchronized (mSatelliteEnabledRequestLock) { 1620 mSatelliteEnableAttributesUpdateRequest = null; 1621 } 1622 break; 1623 } 1624 1625 synchronized (mSatelliteEnabledRequestLock) { 1626 if (mSatelliteEnabledRequest != null) { 1627 plogd("UpdateEnableAttributes: Satellite is being enabled. Need to " 1628 + "wait until enable complete before updating attributes"); 1629 break; 1630 } 1631 if (isSatelliteBeingDisabled()) { 1632 plogd("UpdateEnableAttributes: Satellite is being disabled. Aborting the " 1633 + "enable attributes update request"); 1634 mSatelliteEnableAttributesUpdateRequest = null; 1635 argument.callback.accept(SATELLITE_RESULT_REQUEST_ABORTED); 1636 break; 1637 } 1638 } 1639 onCompleted = obtainMessage(EVENT_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_DONE, request); 1640 SatelliteModemEnableRequestAttributes enableRequestAttributes = 1641 createModemEnableRequest(argument); 1642 if (enableRequestAttributes == null) { 1643 plogw("UpdateEnableAttributes: enableRequestAttributes is null"); 1644 sendErrorAndReportSessionMetrics( 1645 SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE, 1646 argument.callback); 1647 synchronized (mSatelliteEnabledRequestLock) { 1648 mSatelliteEnableAttributesUpdateRequest = null; 1649 } 1650 break; 1651 } 1652 mSatelliteModemInterface.requestSatelliteEnabled( 1653 enableRequestAttributes, onCompleted); 1654 startWaitForUpdateSatelliteEnableAttributesResponseTimer(argument); 1655 break; 1656 } 1657 1658 case EVENT_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_DONE: { 1659 ar = (AsyncResult) msg.obj; 1660 request = (SatelliteControllerHandlerRequest) ar.userObj; 1661 RequestSatelliteEnabledArgument argument = 1662 (RequestSatelliteEnabledArgument) request.argument; 1663 int error = SatelliteServiceUtils.getSatelliteError( 1664 ar, "updateSatelliteEnableAttributes"); 1665 plogd("EVENT_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_DONE = " + error); 1666 1667 /* 1668 * The timer to wait for EVENT_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_DONE might have 1669 * expired and thus the request resources might have been cleaned up. 1670 */ 1671 if (!shouldProcessEventUpdateSatelliteEnableAttributesDone(argument)) { 1672 plogw("The update request ID=" + argument.requestId + " was already processed"); 1673 return; 1674 } 1675 stopWaitForUpdateSatelliteEnableAttributesResponseTimer(argument); 1676 1677 if (error == SATELLITE_RESULT_SUCCESS) { 1678 setDemoModeEnabled(argument.enableDemoMode); 1679 setEmergencyMode(argument.isEmergency); 1680 } 1681 synchronized (mSatelliteEnabledRequestLock) { 1682 mSatelliteEnableAttributesUpdateRequest = null; 1683 } 1684 argument.callback.accept(error); 1685 break; 1686 } 1687 1688 case EVENT_WAIT_FOR_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_RESPONSE_TIMED_OUT: { 1689 RequestSatelliteEnabledArgument argument = 1690 (RequestSatelliteEnabledArgument) msg.obj; 1691 plogw("Timed out to wait for the response from the modem for the request to " 1692 + "update satellite enable attributes, request ID = " + argument.requestId); 1693 synchronized (mSatelliteEnabledRequestLock) { 1694 mSatelliteEnableAttributesUpdateRequest = null; 1695 } 1696 argument.callback.accept(SATELLITE_RESULT_MODEM_TIMEOUT); 1697 break; 1698 } 1699 1700 case CMD_IS_SATELLITE_ENABLED: { 1701 request = (SatelliteControllerHandlerRequest) msg.obj; 1702 onCompleted = obtainMessage(EVENT_IS_SATELLITE_ENABLED_DONE, request); 1703 mSatelliteModemInterface.requestIsSatelliteEnabled(onCompleted); 1704 break; 1705 } 1706 1707 case EVENT_IS_SATELLITE_ENABLED_DONE: { 1708 ar = (AsyncResult) msg.obj; 1709 request = (SatelliteControllerHandlerRequest) ar.userObj; 1710 int error = SatelliteServiceUtils.getSatelliteError(ar, 1711 "isSatelliteEnabled"); 1712 Bundle bundle = new Bundle(); 1713 if (error == SATELLITE_RESULT_SUCCESS) { 1714 if (ar.result == null) { 1715 ploge("isSatelliteEnabled: result is null"); 1716 error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 1717 } else { 1718 boolean enabled = ((int[]) ar.result)[0] == 1; 1719 if (DBG) plogd("isSatelliteEnabled: " + enabled); 1720 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_ENABLED, enabled); 1721 updateSatelliteEnabledState(enabled, "EVENT_IS_SATELLITE_ENABLED_DONE"); 1722 } 1723 } else if (error == SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) { 1724 updateSatelliteSupportedState(false); 1725 } 1726 ((ResultReceiver) request.argument).send(error, bundle); 1727 decrementResultReceiverCount("SC:requestIsSatelliteEnabled"); 1728 break; 1729 } 1730 1731 case CMD_IS_SATELLITE_SUPPORTED: { 1732 request = (SatelliteControllerHandlerRequest) msg.obj; 1733 onCompleted = obtainMessage(EVENT_IS_SATELLITE_SUPPORTED_DONE, request); 1734 mSatelliteModemInterface.requestIsSatelliteSupported(onCompleted); 1735 break; 1736 } 1737 1738 case EVENT_IS_SATELLITE_SUPPORTED_DONE: { 1739 ar = (AsyncResult) msg.obj; 1740 request = (SatelliteControllerHandlerRequest) ar.userObj; 1741 int error = SatelliteServiceUtils.getSatelliteError(ar, "isSatelliteSupported"); 1742 Bundle bundle = new Bundle(); 1743 if (error == SATELLITE_RESULT_SUCCESS) { 1744 if (ar.result == null) { 1745 ploge("isSatelliteSupported: result is null"); 1746 error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 1747 } else { 1748 boolean supported = (boolean) ar.result; 1749 plogd("isSatelliteSupported: " + supported); 1750 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, supported); 1751 updateSatelliteSupportedState(supported); 1752 } 1753 } 1754 ((ResultReceiver) request.argument).send(error, bundle); 1755 break; 1756 } 1757 1758 case CMD_GET_SATELLITE_CAPABILITIES: { 1759 request = (SatelliteControllerHandlerRequest) msg.obj; 1760 onCompleted = obtainMessage(EVENT_GET_SATELLITE_CAPABILITIES_DONE, request); 1761 mSatelliteModemInterface.requestSatelliteCapabilities(onCompleted); 1762 break; 1763 } 1764 1765 case EVENT_GET_SATELLITE_CAPABILITIES_DONE: { 1766 ar = (AsyncResult) msg.obj; 1767 request = (SatelliteControllerHandlerRequest) ar.userObj; 1768 int error = SatelliteServiceUtils.getSatelliteError(ar, 1769 "getSatelliteCapabilities"); 1770 Bundle bundle = new Bundle(); 1771 if (error == SATELLITE_RESULT_SUCCESS) { 1772 if (ar.result == null) { 1773 ploge("getSatelliteCapabilities: result is null"); 1774 error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 1775 } else { 1776 SatelliteCapabilities capabilities = (SatelliteCapabilities) ar.result; 1777 synchronized (mNeedsSatellitePointingLock) { 1778 mNeedsSatellitePointing = capabilities.isPointingRequired(); 1779 } 1780 1781 synchronized (mSatelliteCapabilitiesLock) { 1782 mSatelliteCapabilities = capabilities; 1783 } 1784 overrideSatelliteCapabilitiesIfApplicable(); 1785 if (DBG) plogd("getSatelliteCapabilities: " + getSatelliteCapabilities()); 1786 bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES, 1787 getSatelliteCapabilities()); 1788 } 1789 } 1790 ((ResultReceiver) request.argument).send(error, bundle); 1791 break; 1792 } 1793 1794 case CMD_GET_TIME_SATELLITE_NEXT_VISIBLE: { 1795 request = (SatelliteControllerHandlerRequest) msg.obj; 1796 onCompleted = obtainMessage(EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE, 1797 request); 1798 mSatelliteModemInterface.requestTimeForNextSatelliteVisibility(onCompleted); 1799 break; 1800 } 1801 1802 case EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE: { 1803 ar = (AsyncResult) msg.obj; 1804 request = (SatelliteControllerHandlerRequest) ar.userObj; 1805 int error = SatelliteServiceUtils.getSatelliteError(ar, 1806 "requestTimeForNextSatelliteVisibility"); 1807 Bundle bundle = new Bundle(); 1808 if (error == SATELLITE_RESULT_SUCCESS) { 1809 if (ar.result == null) { 1810 ploge("requestTimeForNextSatelliteVisibility: result is null"); 1811 error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 1812 } else { 1813 int nextVisibilityDuration = ((int[]) ar.result)[0]; 1814 if (DBG) { 1815 plogd("requestTimeForNextSatelliteVisibility: " 1816 + nextVisibilityDuration); 1817 } 1818 bundle.putInt(SatelliteManager.KEY_SATELLITE_NEXT_VISIBILITY, 1819 nextVisibilityDuration); 1820 } 1821 } 1822 ((ResultReceiver) request.argument).send(error, bundle); 1823 decrementResultReceiverCount("SC:requestTimeForNextSatelliteVisibility"); 1824 break; 1825 } 1826 1827 case EVENT_RADIO_STATE_CHANGED: { 1828 synchronized (mIsRadioOnLock) { 1829 logd("EVENT_RADIO_STATE_CHANGED: radioState=" + mCi.getRadioState()); 1830 if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON) { 1831 mIsRadioOn = true; 1832 } else if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF) { 1833 resetCarrierRoamingSatelliteModeParams(); 1834 synchronized (mIsRadioOnLock) { 1835 if (mRadioOffRequested) { 1836 logd("EVENT_RADIO_STATE_CHANGED: set mIsRadioOn to false"); 1837 stopWaitForCellularModemOffTimer(); 1838 mIsRadioOn = false; 1839 mRadioOffRequested = false; 1840 } 1841 } 1842 } 1843 } 1844 1845 if (mCi.getRadioState() != TelephonyManager.RADIO_POWER_UNAVAILABLE) { 1846 if (mSatelliteModemInterface.isSatelliteServiceConnected()) { 1847 Boolean isSatelliteSupported = getIsSatelliteSupported(); 1848 if (isSatelliteSupported == null || !isSatelliteSupported) { 1849 final String caller = "SC:CMD_IS_SATELLITE_SUPPORTED"; 1850 ResultReceiver receiver = new ResultReceiver(this) { 1851 @Override 1852 protected void onReceiveResult( 1853 int resultCode, Bundle resultData) { 1854 decrementResultReceiverCount(caller); 1855 plogd("onRadioStateChanged.requestIsSatelliteSupported: " 1856 + "resultCode=" + resultCode 1857 + ", resultData=" + resultData); 1858 } 1859 }; 1860 sendRequestAsync(CMD_IS_SATELLITE_SUPPORTED, receiver, null); 1861 incrementResultReceiverCount(caller); 1862 } 1863 } 1864 } 1865 break; 1866 } 1867 1868 case CMD_IS_SATELLITE_PROVISIONED: { 1869 request = (SatelliteControllerHandlerRequest) msg.obj; 1870 Message isProvisionedDoneEvent = this.obtainMessage( 1871 EVENT_IS_SATELLITE_PROVISIONED_DONE, 1872 new AsyncResult(request, SATELLITE_RESULT_SUCCESS, null)); 1873 isProvisionedDoneEvent.sendToTarget(); 1874 break; 1875 } 1876 1877 case EVENT_IS_SATELLITE_PROVISIONED_DONE: { 1878 handleIsSatelliteProvisionedDoneEvent((AsyncResult) msg.obj); 1879 break; 1880 } 1881 1882 case EVENT_PENDING_DATAGRAMS: 1883 plogd("Received EVENT_PENDING_DATAGRAMS"); 1884 IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() { 1885 @Override 1886 public void accept(int result) { 1887 plogd("pollPendingSatelliteDatagram result: " + result); 1888 } 1889 }; 1890 pollPendingDatagrams(internalCallback); 1891 break; 1892 1893 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 1894 ar = (AsyncResult) msg.obj; 1895 if (ar.result == null) { 1896 ploge("EVENT_SATELLITE_MODEM_STATE_CHANGED: result is null"); 1897 } else { 1898 handleEventSatelliteModemStateChanged((int) ar.result); 1899 updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(getSatellitePhone()); 1900 } 1901 break; 1902 1903 case EVENT_SET_SATELLITE_PLMN_INFO_DONE: 1904 handleSetSatellitePlmnInfoDoneEvent(msg); 1905 break; 1906 1907 case CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE: { 1908 plogd("CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE"); 1909 request = (SatelliteControllerHandlerRequest) msg.obj; 1910 handleRequestSatelliteAttachRestrictionForCarrierCmd(request); 1911 break; 1912 } 1913 1914 case EVENT_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE_DONE: { 1915 ar = (AsyncResult) msg.obj; 1916 request = (SatelliteControllerHandlerRequest) ar.userObj; 1917 RequestHandleSatelliteAttachRestrictionForCarrierArgument argument = 1918 (RequestHandleSatelliteAttachRestrictionForCarrierArgument) 1919 request.argument; 1920 int subId = argument.subId; 1921 int error = SatelliteServiceUtils.getSatelliteError(ar, 1922 "requestSetSatelliteEnabledForCarrier"); 1923 1924 plogd("EVENT_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE_DONE: subId=" 1925 + subId + " error:" + error); 1926 synchronized (mIsSatelliteEnabledLock) { 1927 if (error == SATELLITE_RESULT_SUCCESS) { 1928 boolean enableSatellite = mSatelliteAttachRestrictionForCarrierArray 1929 .getOrDefault(argument.subId, Collections.emptySet()).isEmpty(); 1930 plogd("EVENT_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE_DONE: " 1931 + "satelliteAttachEnabledForCarrier=" + enableSatellite); 1932 mIsSatelliteAttachEnabledForCarrierArrayPerSub.put(subId, enableSatellite); 1933 } else { 1934 mIsSatelliteAttachEnabledForCarrierArrayPerSub.remove(subId); 1935 } 1936 } 1937 1938 argument.callback.accept(error); 1939 break; 1940 } 1941 1942 case CMD_REQUEST_NTN_SIGNAL_STRENGTH: { 1943 plogd("CMD_REQUEST_NTN_SIGNAL_STRENGTH"); 1944 request = (SatelliteControllerHandlerRequest) msg.obj; 1945 onCompleted = obtainMessage(EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE, request); 1946 mSatelliteModemInterface.requestNtnSignalStrength(onCompleted); 1947 break; 1948 } 1949 1950 case EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE: { 1951 ar = (AsyncResult) msg.obj; 1952 request = (SatelliteControllerHandlerRequest) ar.userObj; 1953 ResultReceiver result = (ResultReceiver) request.argument; 1954 int errorCode = SatelliteServiceUtils.getSatelliteError(ar, 1955 "requestNtnSignalStrength"); 1956 if (errorCode == SATELLITE_RESULT_SUCCESS) { 1957 NtnSignalStrength ntnSignalStrength = (NtnSignalStrength) ar.result; 1958 if (ntnSignalStrength != null) { 1959 synchronized (mNtnSignalsStrengthLock) { 1960 mNtnSignalStrength = ntnSignalStrength; 1961 } 1962 Bundle bundle = new Bundle(); 1963 bundle.putParcelable(KEY_NTN_SIGNAL_STRENGTH, ntnSignalStrength); 1964 result.send(SATELLITE_RESULT_SUCCESS, bundle); 1965 } else { 1966 synchronized (mNtnSignalsStrengthLock) { 1967 if (mNtnSignalStrength.getLevel() != NTN_SIGNAL_STRENGTH_NONE) { 1968 mNtnSignalStrength = new NtnSignalStrength( 1969 NTN_SIGNAL_STRENGTH_NONE); 1970 } 1971 } 1972 ploge("EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE: ntnSignalStrength is null"); 1973 result.send(SatelliteManager.SATELLITE_RESULT_REQUEST_FAILED, null); 1974 } 1975 } else { 1976 synchronized (mNtnSignalsStrengthLock) { 1977 if (mNtnSignalStrength.getLevel() != NTN_SIGNAL_STRENGTH_NONE) { 1978 mNtnSignalStrength = new NtnSignalStrength(NTN_SIGNAL_STRENGTH_NONE); 1979 } 1980 } 1981 result.send(errorCode, null); 1982 } 1983 decrementResultReceiverCount("SC:requestNtnSignalStrength"); 1984 break; 1985 } 1986 1987 case EVENT_NTN_SIGNAL_STRENGTH_CHANGED: { 1988 ar = (AsyncResult) msg.obj; 1989 if (ar.result == null) { 1990 ploge("EVENT_NTN_SIGNAL_STRENGTH_CHANGED: result is null"); 1991 } else { 1992 handleEventNtnSignalStrengthChanged((NtnSignalStrength) ar.result); 1993 updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(getSatellitePhone()); 1994 } 1995 break; 1996 } 1997 1998 case CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING: { 1999 ar = (AsyncResult) msg.obj; 2000 boolean shouldReport = (boolean) ar.result; 2001 if (DBG) { 2002 plogd("CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING: shouldReport=" + shouldReport); 2003 } 2004 handleCmdUpdateNtnSignalStrengthReporting(shouldReport); 2005 break; 2006 } 2007 2008 case EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE: { 2009 ar = (AsyncResult) msg.obj; 2010 request = (SatelliteControllerHandlerRequest) ar.userObj; 2011 boolean shouldReport = (boolean) request.argument; 2012 int errorCode = SatelliteServiceUtils.getSatelliteError(ar, 2013 "EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE: shouldReport=" 2014 + shouldReport); 2015 if (errorCode == SATELLITE_RESULT_SUCCESS) { 2016 mIsModemEnabledReportingNtnSignalStrength.set(shouldReport); 2017 if (mLatestRequestedStateForNtnSignalStrengthReport.get() 2018 != mIsModemEnabledReportingNtnSignalStrength.get()) { 2019 logd("mLatestRequestedStateForNtnSignalStrengthReport does not match with " 2020 + "mIsModemEnabledReportingNtnSignalStrength"); 2021 updateNtnSignalStrengthReporting( 2022 mLatestRequestedStateForNtnSignalStrengthReport.get()); 2023 } 2024 } else { 2025 loge(((boolean) request.argument ? "startSendingNtnSignalStrength" 2026 : "stopSendingNtnSignalStrength") + "returns " + errorCode); 2027 } 2028 break; 2029 } 2030 2031 case EVENT_SERVICE_STATE_CHANGED: { 2032 handleEventServiceStateChanged(); 2033 break; 2034 } 2035 2036 case EVENT_SATELLITE_CAPABILITIES_CHANGED: { 2037 ar = (AsyncResult) msg.obj; 2038 if (ar.result == null) { 2039 ploge("EVENT_SATELLITE_CAPABILITIES_CHANGED: result is null"); 2040 } else { 2041 handleEventSatelliteCapabilitiesChanged((SatelliteCapabilities) ar.result); 2042 } 2043 break; 2044 } 2045 2046 case EVENT_SATELLITE_SUPPORTED_STATE_CHANGED: { 2047 ar = (AsyncResult) msg.obj; 2048 if (ar.result == null) { 2049 ploge("EVENT_SATELLITE_SUPPORTED_STATE_CHANGED: result is null"); 2050 } else { 2051 handleEventSatelliteSupportedStateChanged((boolean) ar.result); 2052 } 2053 break; 2054 } 2055 2056 case EVENT_SATELLITE_CONFIG_DATA_UPDATED: { 2057 handleEventConfigDataUpdated(); 2058 mSatelliteConfigUpdateChangedRegistrants.notifyRegistrants(); 2059 break; 2060 } 2061 2062 case EVENT_NOTIFY_NTN_HYSTERESIS_TIMED_OUT: { 2063 int phoneId = (int) msg.obj; 2064 Phone phone = PhoneFactory.getPhone(phoneId); 2065 updateLastNotifiedNtnModeAndNotify(phone); 2066 break; 2067 } 2068 2069 case EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT: { 2070 boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone); 2071 plogd("EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT:" 2072 + " isCarrierRoamingNtnEligible=" + eligible); 2073 updateLastNotifiedNtnEligibilityAndNotify(eligible); 2074 break; 2075 } 2076 2077 case CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION: { 2078 evaluateESOSProfilesPrioritization(); 2079 break; 2080 } 2081 2082 case CMD_UPDATE_PROVISION_SATELLITE_TOKEN: { 2083 request = (SatelliteControllerHandlerRequest) msg.obj; 2084 RequestProvisionSatelliteArgument argument = 2085 (RequestProvisionSatelliteArgument) request.argument; 2086 onCompleted = obtainMessage(EVENT_UPDATE_PROVISION_SATELLITE_TOKEN_DONE, request); 2087 boolean provisionChanged = updateSatelliteSubscriptionProvisionState( 2088 argument.mSatelliteSubscriberInfoList, argument.mProvisioned); 2089 selectBindingSatelliteSubscription(false); 2090 int subId = getSelectedSatelliteSubId(); 2091 SubscriptionInfo subscriptionInfo = 2092 mSubscriptionManagerService.getSubscriptionInfo(subId); 2093 if (subscriptionInfo == null) { 2094 logw("updateSatelliteToken subId=" + subId + " is not found"); 2095 } else { 2096 String iccId = subscriptionInfo.getIccId(); 2097 argument.setIccId(iccId); 2098 synchronized (mSatelliteTokenProvisionedLock) { 2099 if (!iccId.equals(mLastConfiguredIccId)) { 2100 logd("updateSatelliteSubscription subId=" + subId 2101 + ", iccId=" + iccId + " to modem"); 2102 mSatelliteModemInterface.updateSatelliteSubscription( 2103 iccId, onCompleted); 2104 } 2105 } 2106 } 2107 if (provisionChanged) { 2108 handleEventSatelliteSubscriptionProvisionStateChanged(); 2109 } 2110 2111 // The response is sent immediately because the ICCID has already been 2112 // delivered to the modem. 2113 Bundle bundle = new Bundle(); 2114 bundle.putBoolean( 2115 argument.mProvisioned ? SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS 2116 : SatelliteManager.KEY_DEPROVISION_SATELLITE_TOKENS, true); 2117 argument.mResult.send(SATELLITE_RESULT_SUCCESS, bundle); 2118 decrementResultReceiverCount("SC:provisionSatellite"); 2119 break; 2120 } 2121 2122 case EVENT_UPDATE_PROVISION_SATELLITE_TOKEN_DONE: { 2123 ar = (AsyncResult) msg.obj; 2124 request = (SatelliteControllerHandlerRequest) ar.userObj; 2125 RequestProvisionSatelliteArgument argument = 2126 (RequestProvisionSatelliteArgument) request.argument; 2127 int error = SatelliteServiceUtils.getSatelliteError(ar, 2128 "updateSatelliteSubscription"); 2129 if (error == SATELLITE_RESULT_SUCCESS) { 2130 synchronized (mSatelliteTokenProvisionedLock) { 2131 mLastConfiguredIccId = argument.getIccId(); 2132 } 2133 } 2134 mProvisionMetricsStats.setResultCode(error) 2135 .setIsProvisionRequest(argument.mProvisioned) 2136 .setCarrierId(getSatelliteCarrierId()) 2137 .setIsNtnOnlyCarrier(isNtnOnlyCarrier()) 2138 .reportProvisionMetrics(); 2139 if (argument.mProvisioned) { 2140 mControllerMetricsStats.reportProvisionCount(error); 2141 } else { 2142 mControllerMetricsStats.reportDeprovisionCount(error); 2143 } 2144 logd("updateSatelliteSubscription result=" + error); 2145 break; 2146 } 2147 2148 case EVENT_WIFI_CONNECTIVITY_STATE_CHANGED: { 2149 synchronized (mIsWifiConnectedLock) { 2150 ar = (AsyncResult) msg.obj; 2151 mIsWifiConnected = (boolean) ar.result; 2152 plogd("EVENT_WIFI_CONNECTIVITY_STATE_CHANGED: mIsWifiConnected=" 2153 + mIsWifiConnected); 2154 } 2155 evaluateCarrierRoamingNtnEligibilityChange(); 2156 break; 2157 } 2158 2159 case EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT: { 2160 plogw("Timed out to wait for cellular modem OFF state"); 2161 synchronized (mIsRadioOnLock) { 2162 mRadioOffRequested = false; 2163 } 2164 break; 2165 } 2166 2167 case EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT: { 2168 // TODO: b/366329504 report carrier roaming metrics for multiple subscription IDs. 2169 synchronized (mSupportedSatelliteServicesLock) { 2170 int defaultSubId = mSubscriptionManagerService.getDefaultSubId(); 2171 boolean isEntitled = mSatelliteEntitlementStatusPerCarrier.get(defaultSubId, 2172 false); 2173 mCarrierRoamingSatelliteControllerStats.reportIsDeviceEntitled(defaultSubId, 2174 isEntitled); 2175 } 2176 sendMessageDelayed(obtainMessage( 2177 EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT), 2178 WAIT_FOR_REPORT_ENTITLED_MERTICS_TIMEOUT_MILLIS); 2179 break; 2180 } 2181 2182 case EVENT_SATELLITE_REGISTRATION_FAILURE: 2183 ar = (AsyncResult) msg.obj; 2184 if (ar.result == null) { 2185 loge("EVENT_SATELLITE_REGISTRATION_FAILURE: result is null"); 2186 } else { 2187 handleEventSatelliteRegistrationFailure((int) ar.result); 2188 } 2189 break; 2190 2191 case EVENT_TERRESTRIAL_NETWORK_AVAILABLE_CHANGED: 2192 ar = (AsyncResult) msg.obj; 2193 if (ar.result == null) { 2194 loge("EVENT_TERRESTRIAL_NETWORK_AVAILABLE_CHANGED: result is null"); 2195 } else { 2196 handleEventTerrestrialNetworkAvailableChanged((boolean) ar.result); 2197 } 2198 break; 2199 2200 case EVENT_SET_NETWORK_SELECTION_AUTO_DONE: { 2201 logd("EVENT_SET_NETWORK_SELECTION_AUTO_DONE"); 2202 RequestSatelliteEnabledArgument argument = 2203 (RequestSatelliteEnabledArgument) msg.obj; 2204 sendRequestAsync(CMD_SET_SATELLITE_ENABLED, argument, null); 2205 break; 2206 } 2207 2208 case EVENT_SIGNAL_STRENGTH_CHANGED: { 2209 ar = (AsyncResult) msg.obj; 2210 int phoneId = (int) ar.userObj; 2211 updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify( 2212 PhoneFactory.getPhone(phoneId)); 2213 break; 2214 } 2215 2216 case CMD_UPDATE_SYSTEM_SELECTION_CHANNELS: { 2217 plogd("CMD_UPDATE_SYSTEM_SELECTION_CHANNELS"); 2218 request = (SatelliteControllerHandlerRequest) msg.obj; 2219 onCompleted = 2220 obtainMessage(EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE, request); 2221 UpdateSystemSelectionChannelsArgument argument = 2222 (UpdateSystemSelectionChannelsArgument) request.argument; 2223 mSatelliteModemInterface.updateSystemSelectionChannels( 2224 argument.systemSelectionSpecifiers, onCompleted); 2225 startWaitForUpdateSystemSelectionChannelsResponseTimer(argument); 2226 break; 2227 } 2228 2229 case EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE: { 2230 ar = (AsyncResult) msg.obj; 2231 request = (SatelliteControllerHandlerRequest) ar.userObj; 2232 int error = SatelliteServiceUtils.getSatelliteError( 2233 ar, "updateSystemSelectionChannel"); 2234 plogd("EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE = " + error); 2235 UpdateSystemSelectionChannelsArgument argument = 2236 (UpdateSystemSelectionChannelsArgument) request.argument; 2237 if (shouldProcessEventUpdateSystemSelectionChannelsDone(argument)) { 2238 argument.result.send(error, null); 2239 stopWaitForUpdateSystemSelectionChannelsResponseTimer(argument); 2240 } else { 2241 plogd("EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE: the timer of " 2242 + "the request ID " + argument.requestId 2243 + " has already expired."); 2244 } 2245 break; 2246 } 2247 2248 case EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT: { 2249 UpdateSystemSelectionChannelsArgument argument = 2250 (UpdateSystemSelectionChannelsArgument) msg.obj; 2251 argument.result.send(SATELLITE_RESULT_MODEM_TIMEOUT, null); 2252 plogd("Timed out to wait for response of the system selection channels" 2253 + " update request ID " + argument.requestId); 2254 break; 2255 } 2256 2257 case EVENT_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_CHANGED: { 2258 ar = (AsyncResult) msg.obj; 2259 if (ar.result == null) { 2260 loge("EVENT_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_CHANGED: result is null"); 2261 } else { 2262 handleEventSelectedNbIotSatelliteSubscriptionChanged((int) ar.result); 2263 } 2264 break; 2265 } 2266 2267 case CMD_LOCATION_SERVICE_STATE_CHANGED: 2268 plogd("CMD_LOCATION_SERVICE_STATE_CHANGED"); 2269 // Fall through 2270 case CMD_EVALUATE_CARRIER_ROAMING_NTN_ELIGIBILITY_CHANGE: { 2271 plogd("CMD_EVALUATE_CARRIER_ROAMING_NTN_ELIGIBILITY_CHANGE"); 2272 evaluateCarrierRoamingNtnEligibilityChange(); 2273 boolean eligible = isCarrierRoamingNtnEligible(getSatellitePhone()); 2274 plogd("CMD_EVALUATE_CARRIER_ROAMING_NTN_ELIGIBILITY_CHANGE: eligible=" + eligible); 2275 int selectedSatelliteSubId = getSelectedSatelliteSubId(); 2276 Phone phone = SatelliteServiceUtils.getPhone(selectedSatelliteSubId); 2277 if (eligible) { 2278 synchronized (mSatellitePhoneLock) { 2279 mLastNotifiedNtnEligibility = eligible; 2280 } 2281 phone.notifyCarrierRoamingNtnEligibleStateChanged(eligible); 2282 } 2283 break; 2284 } 2285 2286 case CMD_GET_SATELLITE_ENABLED_FOR_CARRIER: { 2287 request = (SatelliteControllerHandlerRequest) msg.obj; 2288 Phone phone = request.phone; 2289 int subId = phone.getSubId(); 2290 onCompleted = obtainMessage(EVENT_GET_SATELLITE_ENABLED_FOR_CARRIER_DONE, 2291 subId); 2292 int simSlot = SubscriptionManager.getSlotIndex(subId); 2293 plogd("CMD_GET_SATELLITE_ENABLED_FOR_CARRIER: subId=" + subId); 2294 phone.isSatelliteEnabledForCarrier(simSlot, onCompleted); 2295 break; 2296 } 2297 2298 case EVENT_GET_SATELLITE_ENABLED_FOR_CARRIER_DONE: { 2299 ar = (AsyncResult) msg.obj; 2300 2301 if (ar.result == null) { 2302 loge("EVENT_GET_SATELLITE_ENABLED_FOR_CARRIER_DONE: result is null"); 2303 } else { 2304 int subId = (int) ar.userObj; 2305 int error = SatelliteServiceUtils.getSatelliteError( 2306 ar, "isSatelliteEnabledForCarrier"); 2307 boolean satelliteEnabled = (Boolean) ar.result; 2308 plogd("EVENT_GET_SATELLITE_ENABLED_FOR_CARRIER_DONE: subId=" + subId 2309 + " error=" + error + " satelliteEnabled=" + satelliteEnabled); 2310 2311 if (error == SATELLITE_RESULT_SUCCESS) { 2312 synchronized (mIsSatelliteEnabledLock) { 2313 mIsSatelliteAttachEnabledForCarrierArrayPerSub.put( 2314 subId, satelliteEnabled); 2315 } 2316 evaluateEnablingSatelliteForCarrier(subId, 2317 SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, null); 2318 } 2319 } 2320 break; 2321 } 2322 2323 default: 2324 Log.w(TAG, "SatelliteControllerHandler: unexpected message code: " + 2325 msg.what); 2326 break; 2327 } 2328 } 2329 2330 private static final class RequestProvisionSatelliteArgument { 2331 public List<SatelliteSubscriberInfo> mSatelliteSubscriberInfoList; 2332 @NonNull 2333 public ResultReceiver mResult; 2334 public long mRequestId; 2335 public String mIccId; 2336 public boolean mProvisioned; 2337 RequestProvisionSatelliteArgument(List<SatelliteSubscriberInfo> satelliteSubscriberInfoList, ResultReceiver result, boolean provisioned)2338 RequestProvisionSatelliteArgument(List<SatelliteSubscriberInfo> satelliteSubscriberInfoList, 2339 ResultReceiver result, boolean provisioned) { 2340 this.mSatelliteSubscriberInfoList = satelliteSubscriberInfoList; 2341 this.mResult = result; 2342 this.mProvisioned = provisioned; 2343 this.mRequestId = sNextSatelliteEnableRequestId.getAndUpdate( 2344 n -> ((n + 1) % Long.MAX_VALUE)); 2345 } 2346 setIccId(String iccId)2347 public void setIccId(String iccId) { 2348 mIccId = iccId; 2349 } 2350 getIccId()2351 public String getIccId() { 2352 return mIccId; 2353 } 2354 } 2355 handleEventConfigDataUpdated()2356 private void handleEventConfigDataUpdated() { 2357 updateSupportedSatelliteServicesForActiveSubscriptions(); 2358 int[] activeSubIds = mSubscriptionManagerService.getActiveSubIdList(true); 2359 if (activeSubIds != null) { 2360 for (int subId : activeSubIds) { 2361 processNewCarrierConfigData(subId); 2362 } 2363 } else { 2364 ploge("updateSupportedSatelliteServicesForActiveSubscriptions: " 2365 + "activeSubIds is null"); 2366 } 2367 } 2368 notifyRequester(SatelliteControllerHandlerRequest request)2369 private void notifyRequester(SatelliteControllerHandlerRequest request) { 2370 synchronized (request) { 2371 request.notifyAll(); 2372 } 2373 } 2374 2375 /** 2376 * Request to enable or disable the satellite modem and demo mode. If the satellite modem is 2377 * enabled, this will also disable the cellular modem, and if the satellite modem is disabled, 2378 * this will also re-enable the cellular modem. 2379 * 2380 * @param enableSatellite {@code true} to enable the satellite modem and 2381 * {@code false} to disable. 2382 * @param enableDemoMode {@code true} to enable demo mode and {@code false} to disable. 2383 * @param isEmergency {@code true} to enable emergency mode, {@code false} otherwise. 2384 * @param callback The callback to get the error code of the request. 2385 */ requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode, boolean isEmergency, @NonNull IIntegerConsumer callback)2386 public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode, 2387 boolean isEmergency, @NonNull IIntegerConsumer callback) { 2388 plogd("requestSatelliteEnabled enableSatellite: " + enableSatellite 2389 + " enableDemoMode: " + enableDemoMode + " isEmergency: " + isEmergency); 2390 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 2391 int error = evaluateOemSatelliteRequestAllowed(true); 2392 if (error != SATELLITE_RESULT_SUCCESS) { 2393 sendErrorAndReportSessionMetrics(error, result); 2394 return; 2395 } 2396 2397 if (enableSatellite) { 2398 synchronized (mIsRadioOnLock) { 2399 if (!mIsRadioOn) { 2400 ploge("Radio is not on, can not enable satellite"); 2401 sendErrorAndReportSessionMetrics( 2402 SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE, result); 2403 return; 2404 } 2405 if (mRadioOffRequested) { 2406 ploge("Radio is being powering off, can not enable satellite"); 2407 sendErrorAndReportSessionMetrics( 2408 SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE, result); 2409 return; 2410 } 2411 } 2412 2413 if (mTelecomManager.isInEmergencyCall()) { 2414 plogd("requestSatelliteEnabled: reject as emergency call is ongoing."); 2415 sendErrorAndReportSessionMetrics( 2416 SatelliteManager.SATELLITE_RESULT_EMERGENCY_CALL_IN_PROGRESS, result); 2417 return; 2418 } 2419 } else { 2420 /* if disable satellite, always assume demo is also disabled */ 2421 enableDemoMode = false; 2422 } 2423 2424 RequestSatelliteEnabledArgument request = 2425 new RequestSatelliteEnabledArgument(enableSatellite, enableDemoMode, isEmergency, 2426 result); 2427 /** 2428 * Multiple satellite enabled requests are handled as below: 2429 * 1. If there are no ongoing requests, store current request in mSatelliteEnabledRequest 2430 * 2. If there is a ongoing request, then: 2431 * 1. ongoing request = enable, current request = enable: return IN_PROGRESS error 2432 * 2. ongoing request = disable, current request = disable: return IN_PROGRESS error 2433 * 3. ongoing request = disable, current request = enable: return 2434 * SATELLITE_RESULT_ERROR error 2435 * 4. ongoing request = enable, current request = disable: send request to modem 2436 */ 2437 Boolean isSatelliteEnabled = getIsSatelliteEnabled(); 2438 synchronized (mSatelliteEnabledRequestLock) { 2439 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 2440 if (mSatelliteEnabledRequest != null && mNetworkSelectionModeAutoDialog != null 2441 && mNetworkSelectionModeAutoDialog.isShowing() 2442 && request.isEmergency && request.enableSatellite) { 2443 sendErrorAndReportSessionMetrics( 2444 SatelliteManager.SATELLITE_RESULT_ILLEGAL_STATE, 2445 FunctionalUtils.ignoreRemoteException( 2446 mSatelliteEnabledRequest.callback::accept)); 2447 mSatelliteEnabledRequest = null; 2448 mNetworkSelectionModeAutoDialog.dismiss(); 2449 mNetworkSelectionModeAutoDialog = null; 2450 } 2451 } 2452 if (!isSatelliteEnabledRequestInProgress()) { 2453 if (isSatelliteEnabled != null && isSatelliteEnabled == enableSatellite) { 2454 evaluateToUpdateSatelliteEnabledAttributes(result, 2455 SatelliteManager.SATELLITE_RESULT_SUCCESS, request, 2456 mIsDemoModeEnabled, mIsEmergency); 2457 return; 2458 } 2459 2460 if (enableSatellite) { 2461 mSatelliteEnabledRequest = request; 2462 } else { 2463 mSatelliteDisabledRequest = request; 2464 } 2465 } else if (isSatelliteBeingDisabled()) { 2466 int resultCode = SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS; 2467 if (enableSatellite) { 2468 plogw("requestSatelliteEnabled: The enable request cannot be " 2469 + "processed since disable satellite is in progress."); 2470 resultCode = SatelliteManager.SATELLITE_RESULT_DISABLE_IN_PROGRESS; 2471 } else { 2472 plogd("requestSatelliteEnabled: Disable is already in progress."); 2473 } 2474 sendErrorAndReportSessionMetrics(resultCode, result); 2475 return; 2476 } else { 2477 // Satellite is being enabled or satellite enable attributes are being updated 2478 if (enableSatellite) { 2479 if (mSatelliteEnableAttributesUpdateRequest == null) { 2480 /* Satellite is being enabled and framework receive a new enable request to 2481 * update the enable attributes. 2482 */ 2483 evaluateToUpdateSatelliteEnabledAttributes(result, 2484 SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS, 2485 request, mSatelliteEnabledRequest.enableDemoMode, 2486 mSatelliteEnabledRequest.isEmergency); 2487 } else { 2488 /* The enable attributes update request is already being processed. 2489 * Framework can't handle one more request to update enable attributes. 2490 */ 2491 plogd("requestSatelliteEnabled: enable attributes update request is already" 2492 + " in progress."); 2493 sendErrorAndReportSessionMetrics( 2494 SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS, result); 2495 } 2496 return; 2497 } else { 2498 /* Users might want to end the satellite session while it is being enabled, or 2499 * the satellite session need to be disabled for an emergency call. Note: some 2500 * carriers want to disable satellite for prioritizing emergency calls. Thus, 2501 * we need to push the disable request to modem while enable is in progress. 2502 */ 2503 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 2504 plogd("requestSatelliteEnabled: carrierRoamingNbIotNtn flag is disabled"); 2505 sendErrorAndReportSessionMetrics( 2506 SatelliteManager.SATELLITE_RESULT_ENABLE_IN_PROGRESS, result); 2507 return; 2508 } 2509 if (!isDisableSatelliteWhileEnableInProgressSupported()) { 2510 plogd("requestSatelliteEnabled: disable satellite while enable in progress" 2511 + " is not supported"); 2512 sendErrorAndReportSessionMetrics( 2513 SatelliteManager.SATELLITE_RESULT_ENABLE_IN_PROGRESS, result); 2514 return; 2515 } 2516 mSatelliteDisabledRequest = request; 2517 } 2518 } 2519 } 2520 2521 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 2522 Phone satellitePhone = getSatellitePhone(); 2523 if (enableSatellite && satellitePhone != null 2524 && satellitePhone.getServiceStateTracker() != null 2525 && satellitePhone.getServiceStateTracker().getServiceState() 2526 .getIsManualSelection()) { 2527 checkNetworkSelectionModeAuto(request); 2528 } else { 2529 sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null); 2530 } 2531 } else { 2532 sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null); 2533 } 2534 } 2535 isDisableSatelliteWhileEnableInProgressSupported()2536 private boolean isDisableSatelliteWhileEnableInProgressSupported() { 2537 if (mOverriddenDisableSatelliteWhileEnableInProgressSupported != null) { 2538 return mOverriddenDisableSatelliteWhileEnableInProgressSupported; 2539 } 2540 return mContext.getResources().getBoolean( 2541 R.bool.config_support_disable_satellite_while_enable_in_progress); 2542 } 2543 checkNetworkSelectionModeAuto(RequestSatelliteEnabledArgument argument)2544 private void checkNetworkSelectionModeAuto(RequestSatelliteEnabledArgument argument) { 2545 plogd("checkNetworkSelectionModeAuto"); 2546 if (argument.isEmergency) { 2547 // ESOS 2548 getSatellitePhone().setNetworkSelectionModeAutomatic(null); 2549 sendMessageDelayed(obtainMessage(EVENT_SET_NETWORK_SELECTION_AUTO_DONE, argument), 2550 DELAY_WAITING_SET_NETWORK_SELECTION_AUTO_MILLIS); 2551 } else { 2552 // P2P 2553 if (mNetworkSelectionModeAutoDialog != null 2554 && mNetworkSelectionModeAutoDialog.isShowing()) { 2555 logd("requestSatelliteEnabled: already auto network selection mode popup showing"); 2556 sendErrorAndReportSessionMetrics( 2557 SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS, 2558 FunctionalUtils.ignoreRemoteException(argument.callback::accept)); 2559 return; 2560 } 2561 logd("requestSatelliteEnabled: auto network selection mode popup"); 2562 Configuration configuration = Resources.getSystem().getConfiguration(); 2563 boolean nightMode = (configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK) 2564 == Configuration.UI_MODE_NIGHT_YES; 2565 2566 AlertDialog.Builder builder = new AlertDialog.Builder(mContext, nightMode 2567 ? AlertDialog.THEME_DEVICE_DEFAULT_DARK 2568 : AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); 2569 2570 String title = mContext.getResources().getString( 2571 R.string.satellite_manual_selection_state_popup_title); 2572 String message = mContext.getResources().getString( 2573 R.string.satellite_manual_selection_state_popup_message); 2574 String ok = mContext.getResources().getString( 2575 R.string.satellite_manual_selection_state_popup_ok); 2576 String cancel = mContext.getResources().getString( 2577 R.string.satellite_manual_selection_state_popup_cancel); 2578 2579 builder.setTitle(title).setMessage(message) 2580 .setPositiveButton(ok, (dialog, which) -> { 2581 logd("checkNetworkSelectionModeAuto: setPositiveButton"); 2582 getSatellitePhone().setNetworkSelectionModeAutomatic(null); 2583 sendMessageDelayed(obtainMessage(EVENT_SET_NETWORK_SELECTION_AUTO_DONE, 2584 argument), DELAY_WAITING_SET_NETWORK_SELECTION_AUTO_MILLIS); 2585 }) 2586 .setNegativeButton(cancel, (dialog, which) -> { 2587 logd("checkNetworkSelectionModeAuto: setNegativeButton"); 2588 synchronized (mSatelliteEnabledRequestLock) { 2589 mSatelliteEnabledRequest = null; 2590 } 2591 sendErrorAndReportSessionMetrics( 2592 SatelliteManager.SATELLITE_RESULT_ILLEGAL_STATE, 2593 FunctionalUtils.ignoreRemoteException(argument.callback::accept)); 2594 }) 2595 .setOnCancelListener(dialog -> { 2596 logd("checkNetworkSelectionModeAuto: setOnCancelListener"); 2597 synchronized (mSatelliteEnabledRequestLock) { 2598 mSatelliteEnabledRequest = null; 2599 } 2600 sendErrorAndReportSessionMetrics( 2601 SatelliteManager.SATELLITE_RESULT_ILLEGAL_STATE, 2602 FunctionalUtils.ignoreRemoteException(argument.callback::accept)); 2603 }); 2604 mNetworkSelectionModeAutoDialog = builder.create(); 2605 mNetworkSelectionModeAutoDialog.getWindow() 2606 .setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 2607 mNetworkSelectionModeAutoDialog.show(); 2608 } 2609 } 2610 2611 /** 2612 * Validate the newly-received enable attributes against the current ones. If the new attributes 2613 * are valid and different from the current ones, framework will send a request to update the 2614 * enable attributes to modem. Otherwise, framework will return 2615 * {@code SATELLITE_RESULT_INVALID_ARGUMENTS} to the requesting clients. 2616 * 2617 * @param result The callback that returns the result to the requesting client. 2618 * @param resultCode The result code to send back to the requesting client when framework does 2619 * not need to reconfigure modem. 2620 * @param enableRequest The new enable request to update satellite enable attributes. 2621 * @param currentDemoMode The current demo mode at framework. 2622 * @param currentEmergencyMode The current emergency mode at framework. 2623 */ evaluateToUpdateSatelliteEnabledAttributes(@onNull Consumer<Integer> result, @SatelliteManager.SatelliteResult int resultCode, @NonNull RequestSatelliteEnabledArgument enableRequest, boolean currentDemoMode, boolean currentEmergencyMode)2624 private void evaluateToUpdateSatelliteEnabledAttributes(@NonNull Consumer<Integer> result, 2625 @SatelliteManager.SatelliteResult int resultCode, 2626 @NonNull RequestSatelliteEnabledArgument enableRequest, boolean currentDemoMode, 2627 boolean currentEmergencyMode) { 2628 boolean needToReconfigureModem = false; 2629 if (enableRequest.enableDemoMode != currentDemoMode) { 2630 if (enableRequest.enableDemoMode) { 2631 ploge("Moving from real mode to demo mode is rejected"); 2632 sendErrorAndReportSessionMetrics(SATELLITE_RESULT_INVALID_ARGUMENTS, result); 2633 return; 2634 } else { 2635 plogd("Moving from demo mode to real mode. Need to reconfigure" 2636 + " modem with real mode"); 2637 needToReconfigureModem = true; 2638 } 2639 } else if (enableRequest.isEmergency != currentEmergencyMode) { 2640 if (enableRequest.isEmergency) { 2641 plogd("Moving from non-emergency to emergency mode. Need to " 2642 + "reconfigure modem"); 2643 needToReconfigureModem = true; 2644 } else { 2645 plogd("Non-emergency requests can be served during an emergency" 2646 + " satellite session. No need to reconfigure modem."); 2647 } 2648 } 2649 2650 if (needToReconfigureModem) { 2651 synchronized (mSatelliteEnabledRequestLock) { 2652 mSatelliteEnableAttributesUpdateRequest = enableRequest; 2653 } 2654 sendRequestAsync( 2655 CMD_UPDATE_SATELLITE_ENABLE_ATTRIBUTES, enableRequest, null); 2656 } else { 2657 if (resultCode != SatelliteManager.SATELLITE_RESULT_SUCCESS) { 2658 plogd("requestSatelliteEnabled enable satellite is already in progress."); 2659 } 2660 sendErrorAndReportSessionMetrics(resultCode, result); 2661 } 2662 return; 2663 } 2664 2665 /** 2666 * @return {@code true} when either enable request, disable request, or enable attributes update 2667 * request is in progress, {@code false} otherwise. 2668 */ isSatelliteEnabledRequestInProgress()2669 private boolean isSatelliteEnabledRequestInProgress() { 2670 synchronized (mSatelliteEnabledRequestLock) { 2671 plogd("mSatelliteEnabledRequest: " + (mSatelliteEnabledRequest != null) 2672 + ", mSatelliteDisabledRequest: " + (mSatelliteDisabledRequest != null) 2673 + ", mSatelliteEnableAttributesUpdateRequest: " 2674 + (mSatelliteEnableAttributesUpdateRequest != null)); 2675 return (mSatelliteEnabledRequest != null || mSatelliteDisabledRequest != null 2676 || mSatelliteEnableAttributesUpdateRequest != null); 2677 } 2678 } 2679 2680 /** 2681 * Request to get whether the satellite modem is enabled. 2682 * 2683 * @param result The result receiver that returns whether the satellite modem is enabled 2684 * if the request is successful or an error code if the request failed. 2685 */ requestIsSatelliteEnabled(@onNull ResultReceiver result)2686 public void requestIsSatelliteEnabled(@NonNull ResultReceiver result) { 2687 int error = evaluateOemSatelliteRequestAllowed(false); 2688 if (error != SATELLITE_RESULT_SUCCESS) { 2689 result.send(error, null); 2690 return; 2691 } 2692 2693 Boolean isSatelliteEnabled = getIsSatelliteEnabled(); 2694 if (isSatelliteEnabled != null) { 2695 /* We have already successfully queried the satellite modem. */ 2696 Bundle bundle = new Bundle(); 2697 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_ENABLED, isSatelliteEnabled); 2698 result.send(SATELLITE_RESULT_SUCCESS, bundle); 2699 return; 2700 } 2701 2702 sendRequestAsync(CMD_IS_SATELLITE_ENABLED, result, null); 2703 incrementResultReceiverCount("SC:requestIsSatelliteEnabled"); 2704 } 2705 2706 /** 2707 * Get whether the satellite modem is enabled. 2708 * This will return the cached value instead of querying the satellite modem. 2709 * 2710 * @return {@code true} if the satellite modem is enabled and {@code false} otherwise. 2711 */ isSatelliteEnabled()2712 public boolean isSatelliteEnabled() { 2713 synchronized (mIsSatelliteEnabledLock) { 2714 if (mIsSatelliteEnabled == null) return false; 2715 return mIsSatelliteEnabled; 2716 } 2717 } 2718 2719 /** 2720 * Get whether satellite modem is being enabled. 2721 * 2722 * @return {@code true} if the satellite modem is being enabled and {@code false} otherwise. 2723 */ isSatelliteBeingEnabled()2724 public boolean isSatelliteBeingEnabled() { 2725 if (mSatelliteSessionController != null 2726 && mSatelliteSessionController.isInEnablingState()) { 2727 return true; 2728 } 2729 2730 synchronized (mSatelliteEnabledRequestLock) { 2731 return (mSatelliteEnabledRequest != null); 2732 } 2733 } 2734 2735 /** 2736 * Get whether the satellite modem is enabled or being enabled. 2737 * This will return the cached value instead of querying the satellite modem. 2738 * 2739 * @return {@code true} if the satellite modem is enabled or being enabled, {@code false} 2740 * otherwise. 2741 */ isSatelliteEnabledOrBeingEnabled()2742 public boolean isSatelliteEnabledOrBeingEnabled() { 2743 return isSatelliteEnabled() || isSatelliteBeingEnabled(); 2744 } 2745 2746 /** 2747 * Get whether satellite modem is being disabled. 2748 * 2749 * @return {@code true} if the satellite modem is being disabled and {@code false} otherwise. 2750 */ isSatelliteBeingDisabled()2751 public boolean isSatelliteBeingDisabled() { 2752 if (mSatelliteSessionController != null 2753 && mSatelliteSessionController.isInDisablingState()) { 2754 return true; 2755 } 2756 2757 synchronized (mSatelliteEnabledRequestLock) { 2758 return (mSatelliteDisabledRequest != null); 2759 } 2760 } 2761 2762 /** 2763 * Request to get whether the satellite service demo mode is enabled. 2764 * 2765 * @param result The result receiver that returns whether the satellite demo mode is enabled 2766 * if the request is successful or an error code if the request failed. 2767 */ requestIsDemoModeEnabled(@onNull ResultReceiver result)2768 public void requestIsDemoModeEnabled(@NonNull ResultReceiver result) { 2769 int error = evaluateOemSatelliteRequestAllowed(true); 2770 if (error != SATELLITE_RESULT_SUCCESS) { 2771 result.send(error, null); 2772 return; 2773 } 2774 2775 final Bundle bundle = new Bundle(); 2776 bundle.putBoolean(SatelliteManager.KEY_DEMO_MODE_ENABLED, mIsDemoModeEnabled); 2777 result.send(SATELLITE_RESULT_SUCCESS, bundle); 2778 } 2779 2780 /** 2781 * Get whether the satellite service demo mode is enabled. 2782 * 2783 * @return {@code true} if the satellite demo mode is enabled and {@code false} otherwise. 2784 */ isDemoModeEnabled()2785 public boolean isDemoModeEnabled() { 2786 return mIsDemoModeEnabled; 2787 } 2788 2789 /** 2790 * Request to get whether the satellite enabled request is for emergency or not. 2791 * 2792 * @param result The result receiver that returns whether the request is for emergency 2793 * if the request is successful or an error code if the request failed. 2794 */ requestIsEmergencyModeEnabled(@onNull ResultReceiver result)2795 public void requestIsEmergencyModeEnabled(@NonNull ResultReceiver result) { 2796 synchronized (mSatelliteEnabledRequestLock) { 2797 Bundle bundle = new Bundle(); 2798 bundle.putBoolean(SatelliteManager.KEY_EMERGENCY_MODE_ENABLED, 2799 getRequestIsEmergency()); 2800 result.send(SATELLITE_RESULT_SUCCESS, bundle); 2801 } 2802 } 2803 2804 /** 2805 * Request to get whether the satellite service is supported on the device. 2806 * 2807 * @param result The result receiver that returns whether the satellite service is supported on 2808 * the device if the request is successful or an error code if the request failed. 2809 */ requestIsSatelliteSupported(@onNull ResultReceiver result)2810 public void requestIsSatelliteSupported(@NonNull ResultReceiver result) { 2811 int subId = getSelectedSatelliteSubId(); 2812 Boolean isSatelliteSupported = getIsSatelliteSupported(); 2813 if (isSatelliteSupported != null) { 2814 /* We have already successfully queried the satellite modem. */ 2815 Bundle bundle = new Bundle(); 2816 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, isSatelliteSupported); 2817 bundle.putInt(SATELLITE_SUBSCRIPTION_ID, subId); 2818 result.send(SATELLITE_RESULT_SUCCESS, bundle); 2819 return; 2820 } 2821 2822 sendRequestAsync(CMD_IS_SATELLITE_SUPPORTED, result, null); 2823 } 2824 2825 /** 2826 * Request to get the {@link SatelliteCapabilities} of the satellite service. 2827 * 2828 * @param result The result receiver that returns the {@link SatelliteCapabilities} 2829 * if the request is successful or an error code if the request failed. 2830 */ requestSatelliteCapabilities(@onNull ResultReceiver result)2831 public void requestSatelliteCapabilities(@NonNull ResultReceiver result) { 2832 int error = evaluateOemSatelliteRequestAllowed(false); 2833 if (error != SATELLITE_RESULT_SUCCESS) { 2834 result.send(error, null); 2835 return; 2836 } 2837 2838 if (getSatelliteCapabilities() != null) { 2839 Bundle bundle = new Bundle(); 2840 overrideSatelliteCapabilitiesIfApplicable(); 2841 bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES, 2842 getSatelliteCapabilities()); 2843 result.send(SATELLITE_RESULT_SUCCESS, bundle); 2844 return; 2845 } 2846 2847 sendRequestAsync(CMD_GET_SATELLITE_CAPABILITIES, result, null); 2848 } 2849 2850 /** 2851 * Start receiving satellite transmission updates. 2852 * This can be called by the pointing UI when the user starts pointing to the satellite. 2853 * Modem should continue to report the pointing input as the device or satellite moves. 2854 * 2855 * @param errorCallback The callback to get the error code of the request. 2856 * @param callback The callback to notify of satellite transmission updates. 2857 */ startSatelliteTransmissionUpdates( @onNull IIntegerConsumer errorCallback, @NonNull ISatelliteTransmissionUpdateCallback callback)2858 public void startSatelliteTransmissionUpdates( 2859 @NonNull IIntegerConsumer errorCallback, 2860 @NonNull ISatelliteTransmissionUpdateCallback callback) { 2861 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(errorCallback::accept); 2862 int error = evaluateOemSatelliteRequestAllowed(true); 2863 if (error != SATELLITE_RESULT_SUCCESS) { 2864 result.accept(error); 2865 return; 2866 } 2867 2868 final int validSubId = getSelectedSatelliteSubId(); 2869 mPointingAppController.registerForSatelliteTransmissionUpdates(validSubId, callback); 2870 sendRequestAsync(CMD_START_SATELLITE_TRANSMISSION_UPDATES, 2871 new SatelliteTransmissionUpdateArgument(result, callback, validSubId), null); 2872 } 2873 2874 /** 2875 * Stop receiving satellite transmission updates. 2876 * This can be called by the pointing UI when the user stops pointing to the satellite. 2877 * 2878 * @param errorCallback The callback to get the error code of the request. 2879 * @param callback The callback that was passed to {@link #startSatelliteTransmissionUpdates( 2880 * int, IIntegerConsumer, ISatelliteTransmissionUpdateCallback)}. 2881 */ stopSatelliteTransmissionUpdates(@onNull IIntegerConsumer errorCallback, @NonNull ISatelliteTransmissionUpdateCallback callback)2882 public void stopSatelliteTransmissionUpdates(@NonNull IIntegerConsumer errorCallback, 2883 @NonNull ISatelliteTransmissionUpdateCallback callback) { 2884 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(errorCallback::accept); 2885 mPointingAppController.unregisterForSatelliteTransmissionUpdates( 2886 getSelectedSatelliteSubId(), result, callback); 2887 2888 // Even if handler is null - which means there are no listeners, the modem command to stop 2889 // satellite transmission updates might have failed. The callers might want to retry 2890 // sending the command. Thus, we always need to send this command to the modem. 2891 sendRequestAsync(CMD_STOP_SATELLITE_TRANSMISSION_UPDATES, result, null); 2892 } 2893 2894 /** 2895 * Register the subscription with a satellite provider. 2896 * This is needed to register the subscription if the provider allows dynamic registration. 2897 * 2898 * @param token The token to be used as a unique identifier for provisioning with satellite 2899 * gateway. 2900 * @param provisionData Data from the provisioning app that can be used by provisioning server 2901 * @param callback The callback to get the error code of the request. 2902 * 2903 * @return The signal transport used by the caller to cancel the provision request, 2904 * or {@code null} if the request failed. 2905 */ provisionSatelliteService( @onNull String token, @NonNull byte[] provisionData, @NonNull IIntegerConsumer callback)2906 @Nullable public ICancellationSignal provisionSatelliteService( 2907 @NonNull String token, @NonNull byte[] provisionData, 2908 @NonNull IIntegerConsumer callback) { 2909 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 2910 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 2911 List<SatelliteSubscriberInfo> subscriberInfoList = 2912 getNtnOnlySatelliteSubscriberInfoList(result); 2913 if (subscriberInfoList == null) { 2914 return null; 2915 } 2916 ResultReceiver internalReceiver = new ResultReceiver(this) { 2917 @Override 2918 protected void onReceiveResult(int resultCode, Bundle resultData) { 2919 plogd("provisionSatelliteService: resultCode=" + resultCode 2920 + ", resultData=" + resultData); 2921 result.accept(resultCode); 2922 } 2923 }; 2924 provisionSatellite(subscriberInfoList, internalReceiver); 2925 2926 ICancellationSignal cancelTransport = CancellationSignal.createTransport(); 2927 CancellationSignal.fromTransport(cancelTransport).setOnCancelListener(() -> { 2928 deprovisionSatellite(subscriberInfoList, internalReceiver); 2929 mProvisionMetricsStats.setIsCanceled(true); 2930 }); 2931 return cancelTransport; 2932 } else { 2933 int error = evaluateOemSatelliteRequestAllowed(false); 2934 if (error != SATELLITE_RESULT_SUCCESS) { 2935 result.accept(error); 2936 return null; 2937 } 2938 2939 final int validSubId = getSelectedSatelliteSubId(); 2940 if (mSatelliteProvisionCallbacks.containsKey(validSubId)) { 2941 result.accept(SatelliteManager.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS); 2942 return null; 2943 } 2944 2945 Boolean satelliteProvisioned = isDeviceProvisioned(); 2946 if (satelliteProvisioned != null && satelliteProvisioned) { 2947 result.accept(SATELLITE_RESULT_SUCCESS); 2948 return null; 2949 } 2950 2951 sendRequestAsync(CMD_PROVISION_SATELLITE_SERVICE, 2952 new ProvisionSatelliteServiceArgument(token, provisionData, result, validSubId), 2953 null); 2954 2955 ICancellationSignal cancelTransport = CancellationSignal.createTransport(); 2956 CancellationSignal.fromTransport(cancelTransport).setOnCancelListener(() -> { 2957 sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE, 2958 new ProvisionSatelliteServiceArgument(token, provisionData, null, 2959 validSubId), null); 2960 mProvisionMetricsStats.setIsCanceled(true); 2961 }); 2962 return cancelTransport; 2963 } 2964 } 2965 2966 /** 2967 * Unregister the device/subscription with the satellite provider. 2968 * This is needed if the provider allows dynamic registration. Once deprovisioned, 2969 * {@link android.telephony.satellite.SatelliteProvisionStateCallback 2970 * #onSatelliteProvisionStateChanged(boolean)} 2971 * should report as deprovisioned. 2972 * 2973 * @param token The token of the device/subscription to be deprovisioned. 2974 * @param callback The callback to get the error code of the request. 2975 */ deprovisionSatelliteService( @onNull String token, @NonNull IIntegerConsumer callback)2976 public void deprovisionSatelliteService( 2977 @NonNull String token, @NonNull IIntegerConsumer callback) { 2978 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 2979 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 2980 List<SatelliteSubscriberInfo> subscriberInfoList = 2981 getNtnOnlySatelliteSubscriberInfoList(result); 2982 if (subscriberInfoList == null) { 2983 return; 2984 } 2985 ResultReceiver internalReceiver = new ResultReceiver(this) { 2986 @Override 2987 protected void onReceiveResult(int resultCode, Bundle resultData) { 2988 plogd("deprovisionSatelliteService: resultCode=" + resultCode 2989 + ", resultData=" + resultData); 2990 result.accept(resultCode); 2991 } 2992 }; 2993 deprovisionSatellite(subscriberInfoList, internalReceiver); 2994 } else { 2995 int error = evaluateOemSatelliteRequestAllowed(false); 2996 if (error != SATELLITE_RESULT_SUCCESS) { 2997 result.accept(error); 2998 return; 2999 } 3000 3001 if (Boolean.FALSE.equals(isDeviceProvisioned())) { 3002 result.accept(SATELLITE_RESULT_SUCCESS); 3003 return; 3004 } 3005 3006 sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE, 3007 new ProvisionSatelliteServiceArgument(token, null, 3008 result, getSelectedSatelliteSubId()), 3009 null); 3010 } 3011 } 3012 3013 /** 3014 * Registers for the satellite provision state changed. 3015 * 3016 * @param callback The callback to handle the satellite provision state changed event. 3017 * 3018 * @return The {@link SatelliteManager.SatelliteResult} result of the operation. 3019 */ registerForSatelliteProvisionStateChanged( @onNull ISatelliteProvisionStateCallback callback)3020 @SatelliteManager.SatelliteResult public int registerForSatelliteProvisionStateChanged( 3021 @NonNull ISatelliteProvisionStateCallback callback) { 3022 mSatelliteProvisionStateChangedListeners.put(callback.asBinder(), callback); 3023 3024 boolean isProvisioned = Boolean.TRUE.equals(isDeviceProvisioned()); 3025 try { 3026 callback.onSatelliteProvisionStateChanged(isProvisioned); 3027 } catch (RemoteException ex) { 3028 loge("registerForSatelliteProvisionStateChanged: " + ex); 3029 } 3030 synchronized (mDeviceProvisionLock) { 3031 plogd("registerForSatelliteProvisionStateChanged: report current provisioned " 3032 + "state, state=" + isProvisioned); 3033 } 3034 3035 return SATELLITE_RESULT_SUCCESS; 3036 } 3037 3038 /** 3039 * Unregisters for the satellite provision state changed. 3040 * If callback was not registered before, the request will be ignored. 3041 * 3042 * @param callback The callback that was passed to 3043 * {@link #registerForSatelliteProvisionStateChanged(int, ISatelliteProvisionStateCallback)}. 3044 */ unregisterForSatelliteProvisionStateChanged( @onNull ISatelliteProvisionStateCallback callback)3045 public void unregisterForSatelliteProvisionStateChanged( 3046 @NonNull ISatelliteProvisionStateCallback callback) { 3047 mSatelliteProvisionStateChangedListeners.remove(callback.asBinder()); 3048 } 3049 3050 /** 3051 * Request to get whether the device is provisioned with a satellite provider. 3052 * 3053 * @param result The result receiver that returns whether the device is provisioned with a 3054 * satellite provider if the request is successful or an error code if the 3055 * request failed. 3056 */ requestIsSatelliteProvisioned(@onNull ResultReceiver result)3057 public void requestIsSatelliteProvisioned(@NonNull ResultReceiver result) { 3058 int error = evaluateOemSatelliteRequestAllowed(false); 3059 if (error != SATELLITE_RESULT_SUCCESS) { 3060 result.send(error, null); 3061 return; 3062 } 3063 3064 synchronized (mDeviceProvisionLock) { 3065 if (mIsDeviceProvisioned != null) { 3066 Bundle bundle = new Bundle(); 3067 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED, 3068 mIsDeviceProvisioned); 3069 result.send(SATELLITE_RESULT_SUCCESS, bundle); 3070 return; 3071 } 3072 } 3073 3074 sendRequestAsync(CMD_IS_SATELLITE_PROVISIONED, result, null); 3075 incrementResultReceiverCount("SC:requestIsSatelliteProvisioned"); 3076 } 3077 3078 /** 3079 * Registers for modem state changed from satellite modem. 3080 * 3081 * @param callback The callback to handle the satellite modem state changed event. 3082 * 3083 * @return The {@link SatelliteManager.SatelliteResult} result of the operation. 3084 */ registerForSatelliteModemStateChanged( @onNull ISatelliteModemStateCallback callback)3085 @SatelliteManager.SatelliteResult public int registerForSatelliteModemStateChanged( 3086 @NonNull ISatelliteModemStateCallback callback) { 3087 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 3088 plogd("registerForSatelliteModemStateChanged: add Listeners for ModemState"); 3089 mSatelliteRegistrationFailureListeners.put(callback.asBinder(), callback); 3090 mTerrestrialNetworkAvailableChangedListeners.put(callback.asBinder(), callback); 3091 } 3092 if (mSatelliteSessionController != null) { 3093 mSatelliteSessionController.registerForSatelliteModemStateChanged(callback); 3094 } else { 3095 ploge("registerForSatelliteModemStateChanged: mSatelliteSessionController" 3096 + " is not initialized yet"); 3097 return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 3098 } 3099 return SATELLITE_RESULT_SUCCESS; 3100 } 3101 3102 /** 3103 * Unregisters for modem state changed from satellite modem. 3104 * If callback was not registered before, the request will be ignored. 3105 * 3106 * @param callback The callback that was passed to 3107 * {@link #registerForSatelliteModemStateChanged(int, ISatelliteModemStateCallback)}. 3108 */ unregisterForModemStateChanged( @onNull ISatelliteModemStateCallback callback)3109 public void unregisterForModemStateChanged( 3110 @NonNull ISatelliteModemStateCallback callback) { 3111 if (mSatelliteSessionController != null) { 3112 mSatelliteSessionController.unregisterForSatelliteModemStateChanged(callback); 3113 } else { 3114 ploge("unregisterForModemStateChanged: mSatelliteSessionController" 3115 + " is not initialized yet"); 3116 } 3117 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 3118 plogd("unregisterForModemStateChanged: remove Listeners for ModemState"); 3119 mSatelliteRegistrationFailureListeners.remove(callback.asBinder()); 3120 mTerrestrialNetworkAvailableChangedListeners.remove(callback.asBinder()); 3121 } 3122 } 3123 3124 /** 3125 * Register to receive incoming datagrams over satellite. 3126 * 3127 * @param callback The callback to handle incoming datagrams over satellite. 3128 * 3129 * @return The {@link SatelliteManager.SatelliteResult} result of the operation. 3130 */ registerForIncomingDatagram( @onNull ISatelliteDatagramCallback callback)3131 @SatelliteManager.SatelliteResult public int registerForIncomingDatagram( 3132 @NonNull ISatelliteDatagramCallback callback) { 3133 if (!mSatelliteModemInterface.isSatelliteServiceSupported()) { 3134 return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED; 3135 } 3136 plogd("registerForIncomingDatagram: callback=" + callback); 3137 return mDatagramController.registerForSatelliteDatagram( 3138 getSelectedSatelliteSubId(), callback); 3139 } 3140 3141 /** 3142 * Unregister to stop receiving incoming datagrams over satellite. 3143 * If callback was not registered before, the request will be ignored. 3144 * 3145 * @param callback The callback that was passed to 3146 * {@link #registerForIncomingDatagram(int, ISatelliteDatagramCallback)}. 3147 */ unregisterForIncomingDatagram( @onNull ISatelliteDatagramCallback callback)3148 public void unregisterForIncomingDatagram( 3149 @NonNull ISatelliteDatagramCallback callback) { 3150 if (!mSatelliteModemInterface.isSatelliteServiceSupported()) { 3151 return; 3152 } 3153 plogd("unregisterForIncomingDatagram: callback=" + callback); 3154 mDatagramController.unregisterForSatelliteDatagram( 3155 getSelectedSatelliteSubId(), callback); 3156 } 3157 3158 /** 3159 * Poll pending satellite datagrams over satellite. 3160 * 3161 * This method requests modem to check if there are any pending datagrams to be received over 3162 * satellite. If there are any incoming datagrams, they will be received via 3163 * {@link android.telephony.satellite.SatelliteDatagramCallback#onSatelliteDatagramReceived( 3164 * long, SatelliteDatagram, int, Consumer)} 3165 * 3166 * @param callback The callback to get {@link SatelliteManager.SatelliteResult} of the request. 3167 */ pollPendingDatagrams(@onNull IIntegerConsumer callback)3168 public void pollPendingDatagrams(@NonNull IIntegerConsumer callback) { 3169 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 3170 int error = evaluateOemSatelliteRequestAllowed(true); 3171 if (error != SATELLITE_RESULT_SUCCESS) { 3172 result.accept(error); 3173 return; 3174 } 3175 3176 mDatagramController.pollPendingSatelliteDatagrams( 3177 getSelectedSatelliteSubId(), result); 3178 } 3179 3180 /** 3181 * Send datagram over satellite. 3182 * 3183 * Gateway encodes SOS message or location sharing message into a datagram and passes it as 3184 * input to this method. Datagram received here will be passed down to modem without any 3185 * encoding or encryption. 3186 * 3187 * @param datagramType datagram type indicating whether the datagram is of type 3188 * SOS_SMS or LOCATION_SHARING. 3189 * @param datagram encoded gateway datagram which is encrypted by the caller. 3190 * Datagram will be passed down to modem without any encoding or encryption. 3191 * @param needFullScreenPointingUI this is used to indicate pointingUI app to open in 3192 * full screen mode. 3193 * @param callback The callback to get {@link SatelliteManager.SatelliteResult} of the request. 3194 */ sendDatagram(@atelliteManager.DatagramType int datagramType, SatelliteDatagram datagram, boolean needFullScreenPointingUI, @NonNull IIntegerConsumer callback)3195 public void sendDatagram(@SatelliteManager.DatagramType int datagramType, 3196 SatelliteDatagram datagram, boolean needFullScreenPointingUI, 3197 @NonNull IIntegerConsumer callback) { 3198 plogd("sendSatelliteDatagram: datagramType: " + datagramType 3199 + " needFullScreenPointingUI: " + needFullScreenPointingUI); 3200 3201 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 3202 int error = evaluateOemSatelliteRequestAllowed(true); 3203 if (error != SATELLITE_RESULT_SUCCESS) { 3204 result.accept(error); 3205 return; 3206 } 3207 3208 /** 3209 * TODO for NTN-based satellites: Check if satellite is acquired. 3210 */ 3211 if (mNeedsSatellitePointing) { 3212 3213 mPointingAppController.startPointingUI(needFullScreenPointingUI, mIsDemoModeEnabled, 3214 mIsEmergency); 3215 } 3216 3217 mDatagramController.sendSatelliteDatagram(getSelectedSatelliteSubId(), datagramType, 3218 datagram, needFullScreenPointingUI, result); 3219 } 3220 3221 /** 3222 * Request to get the time after which the satellite will be visible. 3223 * 3224 * @param result The result receiver that returns the time after which the satellite will 3225 * be visible if the request is successful or an error code if the request failed. 3226 */ requestTimeForNextSatelliteVisibility(@onNull ResultReceiver result)3227 public void requestTimeForNextSatelliteVisibility(@NonNull ResultReceiver result) { 3228 int error = evaluateOemSatelliteRequestAllowed(true); 3229 if (error != SATELLITE_RESULT_SUCCESS) { 3230 result.send(error, null); 3231 return; 3232 } 3233 3234 sendRequestAsync(CMD_GET_TIME_SATELLITE_NEXT_VISIBLE, result, null); 3235 incrementResultReceiverCount("SC:requestTimeForNextSatelliteVisibility"); 3236 } 3237 3238 /** 3239 * Inform whether the device is aligned with the satellite in both real and demo mode. 3240 * 3241 * @param isAligned {@true} means device is aligned with the satellite, otherwise {@false}. 3242 */ setDeviceAlignedWithSatellite(@onNull boolean isAligned)3243 public void setDeviceAlignedWithSatellite(@NonNull boolean isAligned) { 3244 DemoSimulator.getInstance().setDeviceAlignedWithSatellite(isAligned); 3245 mDatagramController.setDeviceAlignedWithSatellite(isAligned); 3246 if (mSatelliteSessionController != null) { 3247 mSatelliteSessionController.setDeviceAlignedWithSatellite(isAligned); 3248 } else { 3249 ploge("setDeviceAlignedWithSatellite: mSatelliteSessionController" 3250 + " is not initialized yet"); 3251 } 3252 } 3253 3254 /** 3255 * Add a restriction reason for disallowing carrier supported satellite plmn scan and attach 3256 * by modem. After updating restriction list, evaluate if satellite should be enabled/disabled, 3257 * and request modem to enable/disable satellite accordingly if the desired state does not match 3258 * the current state. 3259 * 3260 * @param subId The subId of the subscription to request for. 3261 * @param reason Reason for disallowing satellite communication for carrier. 3262 * @param callback The callback to get the result of the request. 3263 */ addAttachRestrictionForCarrier(int subId, @SatelliteManager.SatelliteCommunicationRestrictionReason int reason, @NonNull IIntegerConsumer callback)3264 public void addAttachRestrictionForCarrier(int subId, 3265 @SatelliteManager.SatelliteCommunicationRestrictionReason int reason, 3266 @NonNull IIntegerConsumer callback) { 3267 logd("addAttachRestrictionForCarrier(" + subId + ", " + reason + ")"); 3268 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 3269 3270 synchronized (mIsSatelliteEnabledLock) { 3271 if (mSatelliteAttachRestrictionForCarrierArray.getOrDefault( 3272 subId, Collections.emptySet()).isEmpty()) { 3273 mSatelliteAttachRestrictionForCarrierArray.put(subId, new HashSet<>()); 3274 } else if (mSatelliteAttachRestrictionForCarrierArray.get(subId).contains(reason)) { 3275 result.accept(SATELLITE_RESULT_SUCCESS); 3276 return; 3277 } 3278 mSatelliteAttachRestrictionForCarrierArray.get(subId).add(reason); 3279 } 3280 RequestHandleSatelliteAttachRestrictionForCarrierArgument request = 3281 new RequestHandleSatelliteAttachRestrictionForCarrierArgument(subId, reason, 3282 result); 3283 sendRequestAsync(CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE, request, 3284 SatelliteServiceUtils.getPhone(subId)); 3285 } 3286 3287 /** 3288 * Remove a restriction reason for disallowing carrier supported satellite plmn scan and attach 3289 * by modem. After updating restriction list, evaluate if satellite should be enabled/disabled, 3290 * and request modem to enable/disable satellite accordingly if the desired state does not match 3291 * the current state. 3292 * 3293 * @param subId The subId of the subscription to request for. 3294 * @param reason Reason for disallowing satellite communication. 3295 * @param callback The callback to get the result of the request. 3296 */ removeAttachRestrictionForCarrier(int subId, @SatelliteManager.SatelliteCommunicationRestrictionReason int reason, @NonNull IIntegerConsumer callback)3297 public void removeAttachRestrictionForCarrier(int subId, 3298 @SatelliteManager.SatelliteCommunicationRestrictionReason int reason, 3299 @NonNull IIntegerConsumer callback) { 3300 logd("removeAttachRestrictionForCarrier(" + subId + ", " + reason + ")"); 3301 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 3302 3303 synchronized (mIsSatelliteEnabledLock) { 3304 if (mSatelliteAttachRestrictionForCarrierArray.getOrDefault( 3305 subId, Collections.emptySet()).isEmpty() 3306 || !mSatelliteAttachRestrictionForCarrierArray.get(subId).contains(reason)) { 3307 result.accept(SATELLITE_RESULT_SUCCESS); 3308 return; 3309 } 3310 mSatelliteAttachRestrictionForCarrierArray.get(subId).remove(reason); 3311 } 3312 RequestHandleSatelliteAttachRestrictionForCarrierArgument request = 3313 new RequestHandleSatelliteAttachRestrictionForCarrierArgument(subId, reason, 3314 result); 3315 sendRequestAsync(CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE, request, 3316 SatelliteServiceUtils.getPhone(subId)); 3317 } 3318 3319 /** 3320 * Get reasons for disallowing satellite communication, as requested by 3321 * {@link #addAttachRestrictionForCarrier(int, int, IIntegerConsumer)}. 3322 * 3323 * @param subId The subId of the subscription to request for. 3324 * 3325 * @return Set of reasons for disallowing satellite attach for carrier. 3326 */ getAttachRestrictionReasonsForCarrier(int subId)3327 @NonNull public Set<Integer> getAttachRestrictionReasonsForCarrier(int subId) { 3328 synchronized (mIsSatelliteEnabledLock) { 3329 Set<Integer> resultSet = 3330 mSatelliteAttachRestrictionForCarrierArray.get(subId); 3331 if (resultSet == null) { 3332 return new HashSet<>(); 3333 } 3334 return new HashSet<>(resultSet); 3335 } 3336 } 3337 3338 /** 3339 * Request to get the signal strength of the satellite connection. 3340 * 3341 * @param result Result receiver to get the error code of the request and the current signal 3342 * strength of the satellite connection. 3343 */ requestNtnSignalStrength(@onNull ResultReceiver result)3344 public void requestNtnSignalStrength(@NonNull ResultReceiver result) { 3345 if (DBG) plogd("requestNtnSignalStrength()"); 3346 3347 int error = evaluateOemSatelliteRequestAllowed(true); 3348 if (error != SATELLITE_RESULT_SUCCESS) { 3349 result.send(error, null); 3350 return; 3351 } 3352 3353 /* In case cache is available, it is not needed to request non-terrestrial signal strength 3354 to modem */ 3355 synchronized (mNtnSignalsStrengthLock) { 3356 if (mNtnSignalStrength.getLevel() != NTN_SIGNAL_STRENGTH_NONE) { 3357 Bundle bundle = new Bundle(); 3358 bundle.putParcelable(KEY_NTN_SIGNAL_STRENGTH, mNtnSignalStrength); 3359 result.send(SATELLITE_RESULT_SUCCESS, bundle); 3360 return; 3361 } 3362 } 3363 3364 Phone phone = SatelliteServiceUtils.getPhone(); 3365 sendRequestAsync(CMD_REQUEST_NTN_SIGNAL_STRENGTH, result, phone); 3366 incrementResultReceiverCount("SC:requestNtnSignalStrength"); 3367 } 3368 3369 /** 3370 * Registers for NTN signal strength changed from satellite modem. If the registration operation 3371 * is not successful, a {@link ServiceSpecificException} that contains 3372 * {@link SatelliteManager.SatelliteResult} will be thrown. 3373 * 3374 * @param callback The callback to handle the NTN signal strength changed event. If the 3375 * operation is successful, {@link INtnSignalStrengthCallback#onNtnSignalStrengthChanged( 3376 * NtnSignalStrength)} will return an instance of {@link NtnSignalStrength} with a value of 3377 * {@link NtnSignalStrength.NtnSignalStrengthLevel} when the signal strength of non-terrestrial 3378 * network has changed. 3379 * 3380 * @throws ServiceSpecificException If the callback registration operation fails. 3381 */ registerForNtnSignalStrengthChanged( @onNull INtnSignalStrengthCallback callback)3382 public void registerForNtnSignalStrengthChanged( 3383 @NonNull INtnSignalStrengthCallback callback) throws RemoteException { 3384 if (DBG) plogd("registerForNtnSignalStrengthChanged()"); 3385 3386 int error = evaluateOemSatelliteRequestAllowed(false); 3387 if (error == SATELLITE_RESULT_SUCCESS) { 3388 mNtnSignalStrengthChangedListeners.put(callback.asBinder(), callback); 3389 synchronized (mNtnSignalsStrengthLock) { 3390 try { 3391 callback.onNtnSignalStrengthChanged(mNtnSignalStrength); 3392 plogd("registerForNtnSignalStrengthChanged: " + mNtnSignalStrength); 3393 } catch (RemoteException ex) { 3394 ploge("registerForNtnSignalStrengthChanged: RemoteException ex=" 3395 + ex); 3396 } 3397 } 3398 } else { 3399 throw new RemoteException(new IllegalStateException("registration fails: " + error)); 3400 } 3401 } 3402 3403 /** 3404 * Unregisters for NTN signal strength changed from satellite modem. 3405 * If callback was not registered before, the request will be ignored. 3406 * 3407 * changed event. 3408 * @param callback The callback that was passed to 3409 * {@link #registerForNtnSignalStrengthChanged(int, INtnSignalStrengthCallback)} 3410 */ unregisterForNtnSignalStrengthChanged( @onNull INtnSignalStrengthCallback callback)3411 public void unregisterForNtnSignalStrengthChanged( 3412 @NonNull INtnSignalStrengthCallback callback) { 3413 if (DBG) plogd("unregisterForNtnSignalStrengthChanged()"); 3414 mNtnSignalStrengthChangedListeners.remove(callback.asBinder()); 3415 } 3416 3417 /** 3418 * Registers for satellite capabilities change event from the satellite service. 3419 * 3420 * @param callback The callback to handle the satellite capabilities changed event. 3421 * 3422 * @return The {@link SatelliteManager.SatelliteResult} result of the operation. 3423 */ registerForCapabilitiesChanged( @onNull ISatelliteCapabilitiesCallback callback)3424 @SatelliteManager.SatelliteResult public int registerForCapabilitiesChanged( 3425 @NonNull ISatelliteCapabilitiesCallback callback) { 3426 if (DBG) plogd("registerForCapabilitiesChanged()"); 3427 3428 int error = evaluateOemSatelliteRequestAllowed(false); 3429 if (error != SATELLITE_RESULT_SUCCESS) return error; 3430 3431 mSatelliteCapabilitiesChangedListeners.put(callback.asBinder(), callback); 3432 return SATELLITE_RESULT_SUCCESS; 3433 } 3434 3435 /** 3436 * Unregisters for satellite capabilities change event from the satellite service. 3437 * If callback was not registered before, the request will be ignored. 3438 * 3439 * changed event. 3440 * @param callback The callback that was passed to 3441 * {@link #registerForCapabilitiesChanged(int, ISatelliteCapabilitiesCallback)} 3442 */ unregisterForCapabilitiesChanged( @onNull ISatelliteCapabilitiesCallback callback)3443 public void unregisterForCapabilitiesChanged( 3444 @NonNull ISatelliteCapabilitiesCallback callback) { 3445 if (DBG) plogd("unregisterForCapabilitiesChanged()"); 3446 mSatelliteCapabilitiesChangedListeners.remove(callback.asBinder()); 3447 } 3448 3449 /** 3450 * Registers for the satellite supported state changed. 3451 * 3452 * @param callback The callback to handle the satellite supported state changed event. 3453 * 3454 * @return The {@link SatelliteManager.SatelliteResult} result of the operation. 3455 */ registerForSatelliteSupportedStateChanged( @onNull IBooleanConsumer callback)3456 @SatelliteManager.SatelliteResult public int registerForSatelliteSupportedStateChanged( 3457 @NonNull IBooleanConsumer callback) { 3458 mSatelliteSupportedStateChangedListeners.put(callback.asBinder(), callback); 3459 return SATELLITE_RESULT_SUCCESS; 3460 } 3461 3462 /** 3463 * Unregisters for the satellite supported state changed. 3464 * If callback was not registered before, the request will be ignored. 3465 * 3466 * @param callback The callback that was passed to 3467 * {@link #registerForSatelliteSupportedStateChanged(IBooleanConsumer)} 3468 */ unregisterForSatelliteSupportedStateChanged( @onNull IBooleanConsumer callback)3469 public void unregisterForSatelliteSupportedStateChanged( 3470 @NonNull IBooleanConsumer callback) { 3471 mSatelliteSupportedStateChangedListeners.remove(callback.asBinder()); 3472 } 3473 3474 /** 3475 * Registers for selected satellite subscription changed event. 3476 * 3477 * @param callback The callback to handle the selected satellite subscription changed event. 3478 * 3479 * @return The {@link SatelliteManager.SatelliteResult} result of the operation. 3480 */ 3481 @SatelliteManager.SatelliteResult registerForSelectedNbIotSatelliteSubscriptionChanged( @onNull ISelectedNbIotSatelliteSubscriptionCallback callback)3482 public int registerForSelectedNbIotSatelliteSubscriptionChanged( 3483 @NonNull ISelectedNbIotSatelliteSubscriptionCallback callback) { 3484 if (DBG) plogd("registerForSelectedNbIotSatelliteSubscriptionChanged()"); 3485 3486 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 3487 plogd("carrierRoamingNbIotNtn flag is disabled"); 3488 return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED; 3489 } 3490 3491 int error = evaluateOemSatelliteRequestAllowed(false); 3492 if (error != SATELLITE_RESULT_SUCCESS) return error; 3493 3494 mSelectedNbIotSatelliteSubscriptionChangedListeners.put(callback.asBinder(), callback); 3495 try { 3496 callback.onSelectedNbIotSatelliteSubscriptionChanged(getSelectedSatelliteSubId()); 3497 } catch (RemoteException ex) { 3498 ploge("registerForSelectedNbIotSatelliteSubscriptionChanged: RemoteException ex=" 3499 + ex); 3500 } 3501 return SATELLITE_RESULT_SUCCESS; 3502 } 3503 3504 /** 3505 * Unregisters for the selected satellite subscription changed event. 3506 * If callback was not registered before, the request will be ignored. 3507 * 3508 * @param callback The callback that was passed to {@link 3509 * #registerForSelectedNbIotSatelliteSubscriptionChanged( 3510 * ISelectedNbIotSatelliteSubscriptionCallback)}. 3511 */ unregisterForSelectedNbIotSatelliteSubscriptionChanged( @onNull ISelectedNbIotSatelliteSubscriptionCallback callback)3512 public void unregisterForSelectedNbIotSatelliteSubscriptionChanged( 3513 @NonNull ISelectedNbIotSatelliteSubscriptionCallback callback) { 3514 if (DBG) plogd("unregisterForSelectedNbIotSatelliteSubscriptionChanged()"); 3515 3516 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 3517 plogd("carrierRoamingNbIotNtn flag is disabled"); 3518 return; 3519 } 3520 3521 int error = evaluateOemSatelliteRequestAllowed(true); 3522 if (error == SATELLITE_RESULT_SUCCESS) { 3523 mSelectedNbIotSatelliteSubscriptionChangedListeners.remove(callback.asBinder()); 3524 } 3525 } 3526 3527 /** 3528 * This API can be used by only CTS to update satellite vendor service package name. 3529 * 3530 * @param servicePackageName The package name of the satellite vendor service. 3531 * @param provisioned Whether satellite should be provisioned or not. 3532 * @return {@code true} if the satellite vendor service is set successfully, 3533 * {@code false} otherwise. 3534 */ setSatelliteServicePackageName(@ullable String servicePackageName, String provisioned)3535 public boolean setSatelliteServicePackageName(@Nullable String servicePackageName, 3536 String provisioned) { 3537 if (!isMockModemAllowed()) { 3538 plogd("setSatelliteServicePackageName: mock modem not allowed"); 3539 return false; 3540 } 3541 3542 // Cached states need to be cleared whenever switching satellite vendor services. 3543 plogd("setSatelliteServicePackageName: Resetting cached states, provisioned=" 3544 + provisioned); 3545 synchronized (mIsSatelliteSupportedLock) { 3546 mIsSatelliteSupported = null; 3547 } 3548 synchronized (mIsSatelliteEnabledLock) { 3549 mIsSatelliteEnabled = null; 3550 } 3551 synchronized (mSatelliteCapabilitiesLock) { 3552 mSatelliteCapabilities = null; 3553 } 3554 mSatelliteModemInterface.setSatelliteServicePackageName(servicePackageName); 3555 return true; 3556 } 3557 3558 /** 3559 * This API can be used by only CTS to update the timeout duration in milliseconds that 3560 * satellite should stay at listening mode to wait for the next incoming page before disabling 3561 * listening mode. 3562 * 3563 * @param timeoutMillis The timeout duration in millisecond. 3564 * @return {@code true} if the timeout duration is set successfully, {@code false} otherwise. 3565 */ setSatelliteListeningTimeoutDuration(long timeoutMillis)3566 public boolean setSatelliteListeningTimeoutDuration(long timeoutMillis) { 3567 if (mSatelliteSessionController == null) { 3568 ploge("mSatelliteSessionController is not initialized yet"); 3569 return false; 3570 } 3571 return mSatelliteSessionController.setSatelliteListeningTimeoutDuration(timeoutMillis); 3572 } 3573 3574 /** 3575 * This API can be used by only CTS to override TN scanning support. 3576 * 3577 * @param concurrentTnScanningSupported Whether concurrent TN scanning is supported. 3578 * @param tnScanningDuringSatelliteSessionAllowed Whether TN scanning is allowed during 3579 * a satellite session. 3580 * @return {@code true} if the TN scanning support is set successfully, 3581 * {@code false} otherwise. 3582 */ setTnScanningSupport(boolean reset, boolean concurrentTnScanningSupported, boolean tnScanningDuringSatelliteSessionAllowed)3583 public boolean setTnScanningSupport(boolean reset, boolean concurrentTnScanningSupported, 3584 boolean tnScanningDuringSatelliteSessionAllowed) { 3585 if (mSatelliteSessionController == null) { 3586 ploge("setTnScanningSupport: mSatelliteSessionController is not initialized yet"); 3587 return false; 3588 } 3589 return mSatelliteSessionController.setTnScanningSupport(reset, 3590 concurrentTnScanningSupported, tnScanningDuringSatelliteSessionAllowed); 3591 } 3592 3593 /** 3594 * This API can be used by only CTS to control ingoring cellular service state event. 3595 * 3596 * @param enabled Whether to enable boolean config. 3597 * @return {@code true} if the value is set successfully, {@code false} otherwise. 3598 */ setSatelliteIgnoreCellularServiceState(boolean enabled)3599 public boolean setSatelliteIgnoreCellularServiceState(boolean enabled) { 3600 plogd("setSatelliteIgnoreCellularServiceState - " + enabled); 3601 if (mSatelliteSessionController == null) { 3602 ploge("setSatelliteIgnoreCellularServiceState is not initialized yet"); 3603 return false; 3604 } 3605 return mSatelliteSessionController.setSatelliteIgnoreCellularServiceState(enabled); 3606 } 3607 3608 /** 3609 * This API can be used by only CTS to control the feature 3610 * {@code config_support_disable_satellite_while_enable_in_progress}. 3611 * 3612 * @param reset Whether to reset the override. 3613 * @param supported Whether to support the feature. 3614 * @return {@code true} if the value is set successfully, {@code false} otherwise. 3615 */ setSupportDisableSatelliteWhileEnableInProgress( boolean reset, boolean supported)3616 public boolean setSupportDisableSatelliteWhileEnableInProgress( 3617 boolean reset, boolean supported) { 3618 if (!isMockModemAllowed()) { 3619 plogd("setSupportDisableSatelliteWhileEnableInProgress: mock modem not allowed"); 3620 return false; 3621 } 3622 3623 plogd("setSupportDisableSatelliteWhileEnableInProgress - reset=" + reset 3624 + ", supported=" + supported); 3625 if (reset) { 3626 mOverriddenDisableSatelliteWhileEnableInProgressSupported = null; 3627 } else { 3628 mOverriddenDisableSatelliteWhileEnableInProgressSupported = supported; 3629 } 3630 return true; 3631 } 3632 3633 /** 3634 * This API can be used by only CTS to override timeout durations used by DatagramController 3635 * module. 3636 * 3637 * @param timeoutMillis The timeout duration in millisecond. 3638 * @return {@code true} if the timeout duration is set successfully, {@code false} otherwise. 3639 */ setDatagramControllerTimeoutDuration( boolean reset, int timeoutType, long timeoutMillis)3640 public boolean setDatagramControllerTimeoutDuration( 3641 boolean reset, int timeoutType, long timeoutMillis) { 3642 plogd("setDatagramControllerTimeoutDuration: reset=" + reset + ", timeoutType=" 3643 + timeoutType + ", timeoutMillis=" + timeoutMillis); 3644 return mDatagramController.setDatagramControllerTimeoutDuration( 3645 reset, timeoutType, timeoutMillis); 3646 } 3647 3648 /** 3649 * This API can be used by only CTS to override the boolean configs used by the 3650 * DatagramController module. 3651 * 3652 * @param enable Whether to enable or disable boolean config. 3653 * @return {@code true} if the boolean config is set successfully, {@code false} otherwise. 3654 */ setDatagramControllerBooleanConfig( boolean reset, int booleanType, boolean enable)3655 public boolean setDatagramControllerBooleanConfig( 3656 boolean reset, int booleanType, boolean enable) { 3657 logd("setDatagramControllerBooleanConfig: reset=" + reset + ", booleanType=" 3658 + booleanType + ", enable=" + enable); 3659 return mDatagramController.setDatagramControllerBooleanConfig( 3660 reset, booleanType, enable); 3661 } 3662 3663 /** 3664 * This API can be used by only CTS to override timeout durations used by SatelliteController 3665 * module. 3666 * 3667 * @param timeoutMillis The timeout duration in millisecond. 3668 * @return {@code true} if the timeout duration is set successfully, {@code false} otherwise. 3669 */ setSatelliteControllerTimeoutDuration( boolean reset, int timeoutType, long timeoutMillis)3670 public boolean setSatelliteControllerTimeoutDuration( 3671 boolean reset, int timeoutType, long timeoutMillis) { 3672 if (!isMockModemAllowed()) { 3673 plogd("setSatelliteControllerTimeoutDuration: mock modem is not allowed"); 3674 return false; 3675 } 3676 plogd("setSatelliteControllerTimeoutDuration: reset=" + reset + ", timeoutType=" 3677 + timeoutType + ", timeoutMillis=" + timeoutMillis); 3678 if (timeoutType == TIMEOUT_TYPE_WAIT_FOR_SATELLITE_ENABLING_RESPONSE) { 3679 if (reset) { 3680 mWaitTimeForSatelliteEnablingResponse = 3681 getWaitForSatelliteEnablingResponseTimeoutMillis(); 3682 } else { 3683 mWaitTimeForSatelliteEnablingResponse = timeoutMillis; 3684 } 3685 plogd("mWaitTimeForSatelliteEnablingResponse=" + mWaitTimeForSatelliteEnablingResponse); 3686 } else if (timeoutType == TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS) { 3687 if (reset) { 3688 mDemoPointingAlignedDurationMillis = 3689 getDemoPointingAlignedDurationMillisFromResources(); 3690 } else { 3691 mDemoPointingAlignedDurationMillis = timeoutMillis; 3692 } 3693 } else if (timeoutType == TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS) { 3694 if (reset) { 3695 mDemoPointingNotAlignedDurationMillis = 3696 getDemoPointingNotAlignedDurationMillisFromResources(); 3697 } else { 3698 mDemoPointingNotAlignedDurationMillis = timeoutMillis; 3699 } 3700 } else if (timeoutType 3701 == TIMEOUT_TYPE_EVALUATE_ESOS_PROFILES_PRIORITIZATION_DURATION_MILLIS) { 3702 if (reset) { 3703 mEvaluateEsosProfilesPrioritizationDurationMillis = 3704 getEvaluateEsosProfilesPrioritizationDurationMillis(); 3705 } else { 3706 mEvaluateEsosProfilesPrioritizationDurationMillis = timeoutMillis; 3707 } 3708 } else { 3709 plogw("Invalid timeoutType=" + timeoutType); 3710 return false; 3711 } 3712 return true; 3713 } 3714 3715 /** 3716 * This API can be used by only CTS to update satellite gateway service package name. 3717 * 3718 * @param servicePackageName The package name of the satellite gateway service. 3719 * @return {@code true} if the satellite gateway service is set successfully, 3720 * {@code false} otherwise. 3721 */ setSatelliteGatewayServicePackageName(@ullable String servicePackageName)3722 public boolean setSatelliteGatewayServicePackageName(@Nullable String servicePackageName) { 3723 if (mSatelliteSessionController == null) { 3724 ploge("mSatelliteSessionController is not initialized yet"); 3725 return false; 3726 } 3727 return mSatelliteSessionController.setSatelliteGatewayServicePackageName( 3728 servicePackageName); 3729 } 3730 3731 /** 3732 * This API can be used by only CTS to update satellite pointing UI app package and class names. 3733 * 3734 * @param packageName The package name of the satellite pointing UI app. 3735 * @param className The class name of the satellite pointing UI app. 3736 * @return {@code true} if the satellite pointing UI app package and class is set successfully, 3737 * {@code false} otherwise. 3738 */ setSatellitePointingUiClassName( @ullable String packageName, @Nullable String className)3739 public boolean setSatellitePointingUiClassName( 3740 @Nullable String packageName, @Nullable String className) { 3741 return mPointingAppController.setSatellitePointingUiClassName(packageName, className); 3742 } 3743 3744 /** 3745 * This API can be used in only testing to override connectivity status in monitoring emergency 3746 * calls and sending EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer. 3747 * 3748 * @param handoverType The type of handover from emergency call to satellite messaging. Use one 3749 * of the following values to enable the override: 3750 * 0 - EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS 3751 * 1 - EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911 3752 * To disable the override, use -1 for handoverType. 3753 * @param delaySeconds The event EVENT_DISPLAY_EMERGENCY_MESSAGE will be sent to Dialer 3754 * delaySeconds after the emergency call starts. 3755 * @return {@code true} if the handover type is set successfully, {@code false} otherwise. 3756 */ setEmergencyCallToSatelliteHandoverType(int handoverType, int delaySeconds)3757 public boolean setEmergencyCallToSatelliteHandoverType(int handoverType, int delaySeconds) { 3758 if (!isMockModemAllowed()) { 3759 ploge("setEmergencyCallToSatelliteHandoverType: mock modem not allowed"); 3760 return false; 3761 } 3762 if (isHandoverTypeValid(handoverType)) { 3763 mEnforcedEmergencyCallToSatelliteHandoverType = handoverType; 3764 mDelayInSendingEventDisplayEmergencyMessage = delaySeconds > 0 ? delaySeconds : 0; 3765 } else { 3766 mEnforcedEmergencyCallToSatelliteHandoverType = 3767 INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE; 3768 mDelayInSendingEventDisplayEmergencyMessage = 0; 3769 } 3770 return true; 3771 } 3772 3773 /** 3774 * This API can be used in only testing to override oem-enabled satellite provision status. 3775 * 3776 * @param reset {@code true} mean the overriding status should not be used, {@code false} 3777 * otherwise. 3778 * @param isProvisioned The overriding provision status. 3779 * @return {@code true} if the provision status is set successfully, {@code false} otherwise. 3780 */ setOemEnabledSatelliteProvisionStatus(boolean reset, boolean isProvisioned)3781 public boolean setOemEnabledSatelliteProvisionStatus(boolean reset, boolean isProvisioned) { 3782 if (!isMockModemAllowed()) { 3783 ploge("setOemEnabledSatelliteProvisionStatus: mock modem not allowed"); 3784 return false; 3785 } 3786 synchronized (mDeviceProvisionLock) { 3787 if (reset) { 3788 mOverriddenIsSatelliteViaOemProvisioned = null; 3789 } else { 3790 mOverriddenIsSatelliteViaOemProvisioned = isProvisioned; 3791 } 3792 } 3793 return true; 3794 } 3795 3796 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) getEnforcedEmergencyCallToSatelliteHandoverType()3797 protected int getEnforcedEmergencyCallToSatelliteHandoverType() { 3798 return mEnforcedEmergencyCallToSatelliteHandoverType; 3799 } 3800 3801 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) getDelayInSendingEventDisplayEmergencyMessage()3802 protected int getDelayInSendingEventDisplayEmergencyMessage() { 3803 return mDelayInSendingEventDisplayEmergencyMessage; 3804 } 3805 isHandoverTypeValid(int handoverType)3806 private boolean isHandoverTypeValid(int handoverType) { 3807 if (handoverType == EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS 3808 || handoverType == EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911) { 3809 return true; 3810 } 3811 return false; 3812 } 3813 3814 /** 3815 * This function is used by {@link SatelliteModemInterface} to notify 3816 * {@link SatelliteController} that the satellite vendor service was just connected. 3817 * <p> 3818 * {@link SatelliteController} will send requests to satellite modem to check whether it support 3819 * satellite and whether it is provisioned. {@link SatelliteController} will use these cached 3820 * values to serve requests from its clients. 3821 * <p> 3822 * Because satellite vendor service might have just come back from a crash, we need to disable 3823 * the satellite modem so that resources will be cleaned up and internal states will be reset. 3824 */ 3825 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) onSatelliteServiceConnected()3826 public void onSatelliteServiceConnected() { 3827 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 3828 plogd("onSatelliteServiceConnected"); 3829 // Vendor service might have just come back from a crash 3830 moveSatelliteToOffStateAndCleanUpResources(SATELLITE_RESULT_MODEM_ERROR); 3831 final String caller = "SC:onSatelliteServiceConnected"; 3832 ResultReceiver receiver = new ResultReceiver(this) { 3833 @Override 3834 protected void onReceiveResult( 3835 int resultCode, Bundle resultData) { 3836 decrementResultReceiverCount(caller); 3837 plogd("onSatelliteServiceConnected.requestIsSatelliteSupported:" 3838 + " resultCode=" + resultCode); 3839 } 3840 }; 3841 requestIsSatelliteSupported(receiver); 3842 incrementResultReceiverCount(caller); 3843 } else { 3844 plogd("onSatelliteServiceConnected: Satellite vendor service is not supported." 3845 + " Ignored the event"); 3846 } 3847 } 3848 3849 /** 3850 * This function is used by {@link com.android.internal.telephony.ServiceStateTracker} to notify 3851 * {@link SatelliteController} that it has received a request to power on or off the cellular 3852 * radio modem. 3853 * 3854 * @param powerOn {@code true} means cellular radio is about to be powered on, {@code false} 3855 * means cellular modem is about to be powered off. 3856 */ onSetCellularRadioPowerStateRequested(boolean powerOn)3857 public void onSetCellularRadioPowerStateRequested(boolean powerOn) { 3858 logd("onSetCellularRadioPowerStateRequested: powerOn=" + powerOn); 3859 3860 synchronized (mIsRadioOnLock) { 3861 mRadioOffRequested = !powerOn; 3862 } 3863 if (powerOn) { 3864 stopWaitForCellularModemOffTimer(); 3865 } else { 3866 requestSatelliteEnabled( 3867 false /* enableSatellite */, false /* enableDemoMode */, 3868 false /* isEmergency */, 3869 new IIntegerConsumer.Stub() { 3870 @Override 3871 public void accept(int result) { 3872 plogd("onSetCellularRadioPowerStateRequested: requestSatelliteEnabled" 3873 + " result=" + result); 3874 } 3875 }); 3876 startWaitForCellularModemOffTimer(); 3877 } 3878 } 3879 3880 /** 3881 * This function is used by {@link com.android.internal.telephony.ServiceStateTracker} to notify 3882 * {@link SatelliteController} that the request to power off the cellular radio modem has 3883 * failed. 3884 */ onPowerOffCellularRadioFailed()3885 public void onPowerOffCellularRadioFailed() { 3886 logd("onPowerOffCellularRadioFailed"); 3887 synchronized (mIsRadioOnLock) { 3888 mRadioOffRequested = false; 3889 stopWaitForCellularModemOffTimer(); 3890 } 3891 } 3892 3893 /** 3894 * Notify SMS received. 3895 * 3896 * @param subId The subId of the subscription used to receive SMS 3897 */ onSmsReceived(int subId)3898 public void onSmsReceived(int subId) { 3899 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 3900 logd("onSmsReceived: carrierRoamingNbIotNtn is disabled"); 3901 return; 3902 } 3903 3904 if (!isSatelliteEnabled()) { 3905 logd("onSmsReceived: satellite is not enabled"); 3906 return; 3907 } 3908 3909 int satelliteSubId = getSelectedSatelliteSubId(); 3910 if (subId != satelliteSubId) { 3911 logd("onSmsReceived: SMS received " + subId 3912 + ", but not satellite subscription " + satelliteSubId); 3913 return; 3914 } 3915 3916 if (mDatagramController != null) { 3917 mDatagramController.onSmsReceived(subId); 3918 } else { 3919 logd("onSmsReceived: DatagramController is not initialized"); 3920 } 3921 3922 mControllerMetricsStats.reportIncomingNtnSmsCount( 3923 SatelliteManager.SATELLITE_RESULT_SUCCESS); 3924 } 3925 3926 /** 3927 * @return {@code true} if satellite is supported via OEM on the device, 3928 * {@code false} otherwise. 3929 */ isSatelliteSupportedViaOem()3930 public boolean isSatelliteSupportedViaOem() { 3931 Boolean supported = isSatelliteSupportedViaOemInternal(); 3932 return (supported != null ? supported : false); 3933 } 3934 3935 /** 3936 * @param subId Subscription ID. 3937 * @return The list of satellite PLMNs used for connecting to satellite networks. 3938 */ 3939 @NonNull getSatellitePlmnsForCarrier(int subId)3940 public List<String> getSatellitePlmnsForCarrier(int subId) { 3941 if (!isSatelliteSupportedViaCarrier(subId)) { 3942 logd("Satellite for carrier is not supported."); 3943 return new ArrayList<>(); 3944 } 3945 3946 return getCarrierPlmnList(subId); 3947 } 3948 3949 /** 3950 * checks if data service is allowed, to add part of list of services supported by satellite 3951 * plmn, when data supported mode 3952 * {@link CarrierConfigManager#KEY_SATELLITE_DATA_SUPPORT_MODE_INT} is restricted mode and no 3953 * data service is included at allowed service info at the entitlement and when allowed service 3954 * info field is present at the entitlement. 3955 * 3956 * @param subId subscription id 3957 * @param plmn The satellite plmn 3958 * @param allowedServiceValues allowed services info supported by entitlement 3959 * @return {@code true} is supports data service else {@code false} 3960 */ isDataServiceUpdateRequired(int subId, String plmn, List<Integer> allowedServiceValues)3961 private boolean isDataServiceUpdateRequired(int subId, String plmn, 3962 List<Integer> allowedServiceValues) { 3963 if (!allowedServiceValues.contains(NetworkRegistrationInfo.SERVICE_TYPE_DATA) 3964 && getCarrierSatelliteDataSupportedModeFromConfig(subId) 3965 == CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED) { 3966 return getSatelliteSupportedServicesFromConfig(subId, plmn) 3967 .contains(NetworkRegistrationInfo.SERVICE_TYPE_DATA); 3968 } 3969 return false; 3970 } 3971 3972 /** 3973 * checks if mms service is allowed, to add part of list of services supported by satellite 3974 * plmn, when no mms service is included at allowed services 3975 * 3976 * @param subId subscription id 3977 * @param plmn The satellite plmn 3978 * @param allowedServiceValues allowed services info supported by entitlement 3979 * @return {@code true} is supports data service else {@code false} 3980 */ isMmsServiceUpdateRequired(int subId, String plmn, List<Integer> allowedServiceValues)3981 private boolean isMmsServiceUpdateRequired(int subId, String plmn, 3982 List<Integer> allowedServiceValues) { 3983 if (!allowedServiceValues.contains(NetworkRegistrationInfo.SERVICE_TYPE_MMS)) { 3984 return getSatelliteSupportedServicesFromConfig(subId, plmn) 3985 .contains(NetworkRegistrationInfo.SERVICE_TYPE_MMS); 3986 } 3987 return false; 3988 } 3989 3990 /** 3991 * Gives the list of satellite services associated with 3992 * {@link CarrierConfigManager#KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE}. 3993 * Note: If this config not found, fallback to 3994 * {@link CarrierConfigManager#KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY}. 3995 * 3996 * @param subId subsctiption id 3997 * @param plmn The satellite plmn 3998 * @return The list of services supported by the carrier associated with the 3999 */ getSatelliteSupportedServicesFromConfig(int subId, String plmn)4000 private List<Integer> getSatelliteSupportedServicesFromConfig(int subId, String plmn) { 4001 if (plmn != null && !plmn.isEmpty()) { 4002 synchronized (mSupportedSatelliteServicesLock) { 4003 if (mSatelliteServicesSupportedByCarriersFromConfig.containsKey(subId)) { 4004 Map<String, Set<Integer>> supportedServices = 4005 mSatelliteServicesSupportedByCarriersFromConfig.get(subId); 4006 if (supportedServices != null && supportedServices.containsKey(plmn)) { 4007 return new ArrayList<>(supportedServices.get(plmn)); 4008 } else { 4009 loge("getSupportedSatelliteServices: subId=" + subId 4010 + ", supportedServices " 4011 + "does not contain key plmn=" + plmn); 4012 } 4013 } else { 4014 loge("getSupportedSatelliteServices: " 4015 + "mSatelliteServicesSupportedByCarriersFromConfig does not contain" 4016 + " key subId=" + subId); 4017 } 4018 } 4019 } 4020 4021 /* Returns default capabilities when carrier config does not contain service capabilities 4022 for the given plmn */ 4023 PersistableBundle config = getPersistableBundle(subId); 4024 int [] defaultCapabilities = config.getIntArray( 4025 KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY); 4026 if (defaultCapabilities == null) { 4027 logd("getSupportedSatelliteServices: defaultCapabilities is null"); 4028 return new ArrayList<>(); 4029 } 4030 List<Integer> capabilitiesList = Arrays.stream( 4031 defaultCapabilities).boxed().collect(Collectors.toList()); 4032 logd("getSupportedSatelliteServices: subId=" + subId 4033 + ", supportedServices does not contain key plmn=" + plmn 4034 + ", return default values " + capabilitiesList); 4035 return capabilitiesList; 4036 } 4037 4038 /** 4039 * @param subId Subscription ID. 4040 * @param plmn The satellite plmn. 4041 * @return The list of services supported by the carrier associated with the {@code subId} for 4042 * the satellite network {@code plmn}. Returns empty list at invalid sub id. 4043 * 4044 */ 4045 @NonNull getSupportedSatelliteServicesForPlmn(int subId, String plmn)4046 public List<Integer> getSupportedSatelliteServicesForPlmn(int subId, String plmn) { 4047 4048 if (!isValidSubscriptionId(subId)) { 4049 logd("getSupportedSatelliteServices: invalid sub id"); 4050 return new ArrayList<>(); 4051 } 4052 synchronized (mSupportedSatelliteServicesLock) { 4053 if (plmn != null && !plmn.isEmpty()) { 4054 Map<String, List<Integer>> allowedServicesList = 4055 mEntitlementServiceTypeMapPerCarrier.get(subId); 4056 if (allowedServicesList != null && allowedServicesList.containsKey(plmn)) { 4057 List<Integer> allowedServiceValues = new ArrayList<>( 4058 allowedServicesList.get(plmn)); 4059 if (allowedServiceValues != null && !allowedServiceValues.isEmpty()) { 4060 if (isDataServiceUpdateRequired(subId, plmn, allowedServiceValues)) { 4061 logd("getSupportedSatelliteServices: data service added to satellite" 4062 + " plmn"); 4063 allowedServiceValues.add(NetworkRegistrationInfo.SERVICE_TYPE_DATA); 4064 } 4065 if (allowedServiceValues.contains(NetworkRegistrationInfo.SERVICE_TYPE_DATA) 4066 && isMmsServiceUpdateRequired(subId, plmn, allowedServiceValues)) { 4067 allowedServiceValues.add(NetworkRegistrationInfo.SERVICE_TYPE_MMS); 4068 } 4069 return allowedServiceValues; 4070 } 4071 } 4072 } 4073 4074 return getSatelliteSupportedServicesFromConfig(subId, plmn); 4075 } 4076 4077 } 4078 4079 /** 4080 * Check whether satellite modem has to attach to a satellite network before sending/receiving 4081 * datagrams. 4082 * 4083 * @return {@code true} if satellite attach is required, {@code false} otherwise. 4084 */ isSatelliteAttachRequired()4085 public boolean isSatelliteAttachRequired() { 4086 SatelliteCapabilities satelliteCapabilities = getSatelliteCapabilities(); 4087 if (satelliteCapabilities == null) { 4088 ploge("isSatelliteAttachRequired: mSatelliteCapabilities is null"); 4089 return false; 4090 } 4091 if (satelliteCapabilities.getSupportedRadioTechnologies().contains( 4092 SatelliteManager.NT_RADIO_TECHNOLOGY_NB_IOT_NTN)) { 4093 return true; 4094 } 4095 return false; 4096 } 4097 4098 /** 4099 * @return {@code true} if satellite is supported via carrier by any subscription on the device, 4100 * {@code false} otherwise. 4101 */ isSatelliteSupportedViaCarrier()4102 public boolean isSatelliteSupportedViaCarrier() { 4103 for (Phone phone : PhoneFactory.getPhones()) { 4104 if (isSatelliteSupportedViaCarrier(phone.getSubId())) { 4105 return true; 4106 } 4107 } 4108 return false; 4109 } 4110 4111 /** 4112 * @return {@code true} if satellite emergency messaging is supported via carrier by any 4113 * subscription on the device, {@code false} otherwise. 4114 */ isSatelliteEmergencyMessagingSupportedViaCarrier()4115 public boolean isSatelliteEmergencyMessagingSupportedViaCarrier() { 4116 for (Phone phone : PhoneFactory.getPhones()) { 4117 if (isSatelliteEmergencyMessagingSupportedViaCarrier(phone.getSubId())) { 4118 return true; 4119 } 4120 } 4121 return false; 4122 } 4123 isSatelliteEmergencyMessagingSupportedViaCarrier(int subId)4124 private boolean isSatelliteEmergencyMessagingSupportedViaCarrier(int subId) { 4125 if (!isSatelliteSupportedViaCarrier(subId)) { 4126 return false; 4127 } 4128 PersistableBundle config = getPersistableBundle(subId); 4129 return config.getBoolean(KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL); 4130 } 4131 4132 /** 4133 * @return {@code Pair<true, subscription ID>} if any subscription on the device is connected to 4134 * satellite, {@code Pair<false, null>} otherwise. 4135 */ isUsingNonTerrestrialNetworkViaCarrier()4136 Pair<Boolean, Integer> isUsingNonTerrestrialNetworkViaCarrier() { 4137 for (Phone phone : PhoneFactory.getPhones()) { 4138 ServiceState serviceState = phone.getServiceState(); 4139 if (serviceState != null && serviceState.isUsingNonTerrestrialNetwork()) { 4140 return new Pair<>(true, phone.getSubId()); 4141 } 4142 } 4143 return new Pair<>(false, null); 4144 } 4145 4146 /** 4147 * @return {@code true} and the corresponding subId if the device is connected to 4148 * satellite via any carrier within the 4149 * {@link CarrierConfigManager#KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT} 4150 * duration, {@code false} and null otherwise. 4151 */ isSatelliteConnectedViaCarrierWithinHysteresisTime()4152 public Pair<Boolean, Integer> isSatelliteConnectedViaCarrierWithinHysteresisTime() { 4153 Pair<Boolean, Integer> ntnConnectedState = isUsingNonTerrestrialNetworkViaCarrier(); 4154 if (ntnConnectedState.first) { 4155 return ntnConnectedState; 4156 } 4157 for (Phone phone : PhoneFactory.getPhones()) { 4158 if (isInSatelliteModeForCarrierRoaming(phone)) { 4159 logd("isSatelliteConnectedViaCarrierWithinHysteresisTime: " 4160 + "subId:" + phone.getSubId() 4161 + " is connected to satellite within hysteresis time"); 4162 return new Pair<>(true, phone.getSubId()); 4163 } 4164 } 4165 return new Pair<>(false, null); 4166 } 4167 4168 /** 4169 * Get whether device is connected to satellite via carrier. 4170 * 4171 * @param phone phone object 4172 * @return {@code true} if the device is connected to satellite using the phone within the 4173 * {@link CarrierConfigManager#KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT} 4174 * duration, {@code false} otherwise. 4175 */ isInSatelliteModeForCarrierRoaming(@ullable Phone phone)4176 public boolean isInSatelliteModeForCarrierRoaming(@Nullable Phone phone) { 4177 if (phone == null) { 4178 return false; 4179 } 4180 4181 int subId = phone.getSubId(); 4182 int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId); 4183 if (carrierRoamingNtnConnectType == CARRIER_ROAMING_NTN_CONNECT_MANUAL) { 4184 return isInCarrierRoamingNbIotNtn(phone); 4185 } 4186 4187 if (!isSatelliteSupportedViaCarrier(subId)) { 4188 return false; 4189 } 4190 4191 ServiceState serviceState = phone.getServiceState(); 4192 if (serviceState == null) { 4193 return false; 4194 } 4195 4196 if (serviceState.isUsingNonTerrestrialNetwork()) { 4197 return true; 4198 } 4199 4200 if (getWwanIsInService(serviceState) 4201 || serviceState.getState() == ServiceState.STATE_POWER_OFF) { 4202 // Device is connected to terrestrial network which has coverage or radio is turned off 4203 resetCarrierRoamingSatelliteModeParams(subId); 4204 return false; 4205 } 4206 4207 synchronized (mSatelliteConnectedLock) { 4208 Long lastDisconnectedTime = mLastSatelliteDisconnectedTimesMillis.get(subId); 4209 long satelliteConnectionHysteresisTime = 4210 getSatelliteConnectionHysteresisTimeMillis(subId); 4211 if (lastDisconnectedTime != null 4212 && (getElapsedRealtime() - lastDisconnectedTime) 4213 <= satelliteConnectionHysteresisTime) { 4214 logd("isInSatelliteModeForCarrierRoaming: " + "subId:" + subId 4215 + " is connected to satellite within hysteresis time"); 4216 return true; 4217 } else { 4218 resetCarrierRoamingSatelliteModeParams(subId); 4219 return false; 4220 } 4221 } 4222 } 4223 4224 /** 4225 * @return {@code true} if should exit satellite mode unless already sent a datagram in this 4226 * esos session. 4227 */ shouldTurnOffCarrierSatelliteForEmergencyCall()4228 public boolean shouldTurnOffCarrierSatelliteForEmergencyCall() { 4229 return !mDatagramController.isEmergencyCommunicationEstablished() 4230 && getConfigForSubId(getSelectedSatelliteSubId()).getBoolean( 4231 KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL); 4232 } 4233 4234 /** 4235 * Return whether the satellite request is for an emergency or not. 4236 * 4237 * @return {@code true} if the satellite request is for an emergency and 4238 * {@code false} otherwise. 4239 */ getRequestIsEmergency()4240 public boolean getRequestIsEmergency() { 4241 return mIsEmergency; 4242 } 4243 4244 /** 4245 * @return {@code true} if device is in carrier roaming nb iot ntn mode, 4246 * else {@return false} 4247 */ isInCarrierRoamingNbIotNtn()4248 public boolean isInCarrierRoamingNbIotNtn() { 4249 return isInCarrierRoamingNbIotNtn(getSatellitePhone()); 4250 } 4251 4252 /** 4253 * @return {@code true} if phone is in carrier roaming nb iot ntn mode, 4254 * else {@return false} 4255 */ isInCarrierRoamingNbIotNtn(@ullable Phone phone)4256 public boolean isInCarrierRoamingNbIotNtn(@Nullable Phone phone) { 4257 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 4258 plogd("isInCarrierRoamingNbIotNtn: carrier roaming nb iot ntn " 4259 + "feature flag is disabled"); 4260 return false; 4261 } 4262 4263 if (!isSatelliteEnabled()) { 4264 plogd("iisInCarrierRoamingNbIotNtn: satellite is disabled"); 4265 return false; 4266 } 4267 4268 if (phone == null) { 4269 plogd("isInCarrierRoamingNbIotNtn: phone is null"); 4270 return false; 4271 } 4272 4273 int subId = phone.getSubId(); 4274 if (!isSatelliteSupportedViaCarrier(subId)) { 4275 plogd("isInCarrierRoamingNbIotNtn[phoneId=" + phone.getPhoneId() 4276 + "]: satellite is not supported via carrier"); 4277 return false; 4278 } 4279 4280 int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId); 4281 if (carrierRoamingNtnConnectType != CARRIER_ROAMING_NTN_CONNECT_MANUAL) { 4282 plogd("isInCarrierRoamingNbIotNtn[phoneId=" + phone.getPhoneId() + "]: not manual " 4283 + "connect. carrierRoamingNtnConnectType = " + carrierRoamingNtnConnectType); 4284 return false; 4285 } 4286 4287 if (subId != getSelectedSatelliteSubId()) { 4288 plogd("isInCarrierRoamingNbIotNtn: subId=" + subId 4289 + " does not match satellite subId=" + getSelectedSatelliteSubId()); 4290 return false; 4291 } 4292 4293 plogd("isInCarrierRoamingNbIotNtn: carrier roaming ntn eligible for phone" 4294 + " associated with subId " + phone.getSubId()); 4295 return true; 4296 } 4297 4298 /** 4299 * Return capabilities of carrier roaming satellite network. 4300 * 4301 * @param phone phone object 4302 * @return The list of services supported by the carrier associated with the {@code subId} 4303 */ 4304 @NonNull getCapabilitiesForCarrierRoamingSatelliteMode(Phone phone)4305 public List<Integer> getCapabilitiesForCarrierRoamingSatelliteMode(Phone phone) { 4306 synchronized (mSatelliteConnectedLock) { 4307 int subId = phone.getSubId(); 4308 if (mSatModeCapabilitiesForCarrierRoaming.containsKey(subId)) { 4309 return mSatModeCapabilitiesForCarrierRoaming.get(subId); 4310 } 4311 } 4312 4313 return new ArrayList<>(); 4314 } 4315 4316 /** 4317 * Request to get the {@link SatelliteSessionStats} of the satellite service. 4318 * 4319 * @param subId The subId of the subscription to the satellite session stats for. 4320 * @param result The result receiver that returns the {@link SatelliteSessionStats} 4321 * if the request is successful or an error code if the request failed. 4322 */ requestSatelliteSessionStats(int subId, @NonNull ResultReceiver result)4323 public void requestSatelliteSessionStats(int subId, @NonNull ResultReceiver result) { 4324 mSessionMetricsStats.requestSatelliteSessionStats(subId, result); 4325 } 4326 4327 /** 4328 * Get the carrier-enabled emergency call wait for connection timeout millis 4329 */ getCarrierEmergencyCallWaitForConnectionTimeoutMillis()4330 public long getCarrierEmergencyCallWaitForConnectionTimeoutMillis() { 4331 long maxTimeoutMillis = 0; 4332 for (Phone phone : PhoneFactory.getPhones()) { 4333 if (!isSatelliteEmergencyMessagingSupportedViaCarrier(phone.getSubId())) { 4334 continue; 4335 } 4336 4337 int timeoutMillis = 4338 getCarrierEmergencyCallWaitForConnectionTimeoutMillis(phone.getSubId()); 4339 // Prioritize getting the timeout duration from the phone that is in satellite mode 4340 // with carrier roaming 4341 if (isInSatelliteModeForCarrierRoaming(phone)) { 4342 return timeoutMillis; 4343 } 4344 if (maxTimeoutMillis < timeoutMillis) { 4345 maxTimeoutMillis = timeoutMillis; 4346 } 4347 } 4348 if (maxTimeoutMillis != 0) { 4349 return maxTimeoutMillis; 4350 } 4351 return DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS; 4352 } 4353 getCarrierEmergencyCallWaitForConnectionTimeoutMillis(int subId)4354 public int getCarrierEmergencyCallWaitForConnectionTimeoutMillis(int subId) { 4355 PersistableBundle config = getPersistableBundle(subId); 4356 return config.getInt(KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT); 4357 } 4358 4359 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) getElapsedRealtime()4360 protected long getElapsedRealtime() { 4361 return SystemClock.elapsedRealtime(); 4362 } 4363 4364 /** 4365 * Register the handler for SIM Refresh notifications. 4366 * @param handler Handler for notification message. 4367 * @param what User-defined message code. 4368 */ registerIccRefresh(Handler handler, int what)4369 public void registerIccRefresh(Handler handler, int what) { 4370 for (Phone phone : PhoneFactory.getPhones()) { 4371 CommandsInterface ci = phone.mCi; 4372 ci.registerForIccRefresh(handler, what, null); 4373 } 4374 } 4375 4376 /** 4377 * Unregister the handler for SIM Refresh notifications. 4378 * @param handler Handler for notification message. 4379 */ unRegisterIccRefresh(Handler handler)4380 public void unRegisterIccRefresh(Handler handler) { 4381 for (Phone phone : PhoneFactory.getPhones()) { 4382 CommandsInterface ci = phone.mCi; 4383 ci.unregisterForIccRefresh(handler); 4384 } 4385 } 4386 4387 /** 4388 * To use the satellite service, update the EntitlementStatus, PlmnAllowedList, barred plmn list 4389 * data plan, service type, data service policy and voice service policy after receiving the 4390 * satellite configuration from the entitlement server. If satellite entitlement is enabled, 4391 * enable satellite for the carrier. Otherwise, disable satellite. 4392 * 4393 * @param subId Subscription ID 4394 * @param entitlementEnabled {@code true} enables Satellite entitlement service. 4395 * @param allowedPlmnList Plmn [MCC+MNC] list of codes to determine if satellite 4396 * communication is allowed. Ex : "123123,12310". 4397 * @param barredPlmnList Plmn [MCC+MNC] list of codes to determine if satellite 4398 * communication is not allowed. Ex : "123123,12310". 4399 * @param plmnDataPlanMap data plan per plmn of type {@link SatelliteDataPlan}. 4400 * Ex : {"302820":0, "31026":1}. 4401 * @param plmnServiceTypeMap list of supported services per plmn of type 4402 * {@link NetworkRegistrationInfo.ServiceType}). 4403 * Ex : {"302820":[1,3],"31026":[2,3]}. 4404 * @param plmnDataServicePolicyMap data support mode per plmn map of types 4405 * {@link CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE}. 4406 * Ex : {"302820":2, "31026":1}. 4407 * @param plmnVoiceServicePolicyMap voice support mode per plmn map of types 4408 * {@link CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE}. 4409 * Ex : {"302820":2, "31026":1}. 4410 * @param callback callback for accept. 4411 */ onSatelliteEntitlementStatusUpdated(int subId, boolean entitlementEnabled, @Nullable List<String> allowedPlmnList, @Nullable List<String> barredPlmnList, @Nullable Map<String,Integer> plmnDataPlanMap, @Nullable Map<String,List<Integer>> plmnServiceTypeMap, @Nullable Map<String,Integer> plmnDataServicePolicyMap, @Nullable Map<String,Integer> plmnVoiceServicePolicyMap, @Nullable IIntegerConsumer callback)4412 public void onSatelliteEntitlementStatusUpdated(int subId, boolean entitlementEnabled, 4413 @Nullable List<String> allowedPlmnList, @Nullable List<String> barredPlmnList, 4414 @Nullable Map<String,Integer> plmnDataPlanMap, 4415 @Nullable Map<String,List<Integer>> plmnServiceTypeMap, 4416 @Nullable Map<String,Integer> plmnDataServicePolicyMap, 4417 @Nullable Map<String,Integer> plmnVoiceServicePolicyMap, 4418 @Nullable IIntegerConsumer callback) { 4419 if (callback == null) { 4420 callback = new IIntegerConsumer.Stub() { 4421 @Override 4422 public void accept(int result) { 4423 logd("updateSatelliteEntitlementStatus:" + result); 4424 } 4425 }; 4426 } 4427 if (allowedPlmnList == null) { 4428 allowedPlmnList = new ArrayList<>(); 4429 } 4430 if (barredPlmnList == null) { 4431 barredPlmnList = new ArrayList<>(); 4432 } 4433 if (plmnDataPlanMap == null) { 4434 plmnDataPlanMap = new HashMap<>(); 4435 } 4436 if (plmnServiceTypeMap == null) { 4437 plmnServiceTypeMap = new HashMap<>(); 4438 } 4439 if (plmnDataServicePolicyMap == null) { 4440 plmnDataServicePolicyMap = new HashMap<>(); 4441 } 4442 if (plmnVoiceServicePolicyMap == null) { 4443 plmnVoiceServicePolicyMap = new HashMap<>(); 4444 } 4445 logd("onSatelliteEntitlementStatusUpdated subId=" + subId + ", entitlementEnabled=" 4446 + entitlementEnabled + ", allowedPlmnList=[" 4447 + String.join(",", allowedPlmnList) + "]" + ", barredPlmnList=[" 4448 + String.join(",", barredPlmnList) + "]" 4449 + ", plmnDataPlanMap =" + plmnDataPlanMap.toString() 4450 + ", plmnServiceTypeMap =" + plmnServiceTypeMap.toString() 4451 + ", plmnDataServicePolicyMap=" + plmnDataServicePolicyMap.toString() 4452 + ", plmnVoiceServicePolicyMap=" + plmnVoiceServicePolicyMap.toString()); 4453 4454 synchronized (mSupportedSatelliteServicesLock) { 4455 if (mSatelliteEntitlementStatusPerCarrier.get(subId, false) != entitlementEnabled) { 4456 logd("update the carrier satellite enabled to " + entitlementEnabled); 4457 mSatelliteEntitlementStatusPerCarrier.put(subId, entitlementEnabled); 4458 mCarrierRoamingSatelliteControllerStats.reportIsDeviceEntitled(subId, 4459 entitlementEnabled); 4460 if (hasMessages(EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT)) { 4461 removeMessages(EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT); 4462 sendMessageDelayed(obtainMessage( 4463 EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT), 4464 WAIT_FOR_REPORT_ENTITLED_MERTICS_TIMEOUT_MILLIS); 4465 } 4466 try { 4467 mSubscriptionManagerService.setSubscriptionProperty(subId, 4468 SATELLITE_ENTITLEMENT_STATUS, entitlementEnabled ? "1" : "0"); 4469 } catch (IllegalArgumentException | SecurityException e) { 4470 loge("onSatelliteEntitlementStatusUpdated: setSubscriptionProperty, e=" + e); 4471 } 4472 } 4473 4474 if (isValidPlmnList(allowedPlmnList) && isValidPlmnList(barredPlmnList)) { 4475 mMergedPlmnListPerCarrier.remove(subId); 4476 mEntitlementPlmnListPerCarrier.put(subId, allowedPlmnList); 4477 mEntitlementBarredPlmnListPerCarrier.put(subId, barredPlmnList); 4478 mEntitlementDataPlanMapPerCarrier.put(subId, plmnDataPlanMap); 4479 mEntitlementDataServicePolicyMapPerCarrier.put(subId, plmnDataServicePolicyMap); 4480 mEntitlementVoiceServicePolicyMapPerCarrier.put(subId, plmnVoiceServicePolicyMap); 4481 updateAndNotifyChangesInCarrierRoamingNtnAvailableServices(subId, 4482 plmnServiceTypeMap); 4483 updatePlmnListPerCarrier(subId); 4484 4485 configureSatellitePlmnForCarrier(subId); 4486 evaluateEnablingSatelliteForCarrier(subId, 4487 SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, null); 4488 mSubscriptionManagerService.setSatelliteEntitlementInfo(subId, allowedPlmnList, 4489 barredPlmnList, plmnDataPlanMap, plmnServiceTypeMap, 4490 plmnDataServicePolicyMap, plmnVoiceServicePolicyMap); 4491 4492 } else { 4493 loge("onSatelliteEntitlementStatusUpdated: either invalid allowedPlmnList " 4494 + "or invalid barredPlmnList"); 4495 } 4496 4497 if (mSatelliteEntitlementStatusPerCarrier.get(subId, false)) { 4498 removeAttachRestrictionForCarrier(subId, 4499 SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT, callback); 4500 } else { 4501 addAttachRestrictionForCarrier(subId, 4502 SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT, callback); 4503 } 4504 } 4505 } 4506 4507 /** 4508 * A list of PLMNs is considered valid if either the list is empty or all PLMNs in the list 4509 * are valid. 4510 */ isValidPlmnList(@onNull List<String> plmnList)4511 private boolean isValidPlmnList(@NonNull List<String> plmnList) { 4512 for (String plmn : plmnList) { 4513 if (!TelephonyUtils.isValidPlmn(plmn)) { 4514 ploge("Invalid PLMN = " + plmn); 4515 return false; 4516 } 4517 } 4518 return true; 4519 } 4520 4521 /** 4522 * If we have not successfully queried the satellite modem for its satellite service support, 4523 * we will retry the query one more time. Otherwise, we will return the cached result. 4524 */ isSatelliteSupportedViaOemInternal()4525 private Boolean isSatelliteSupportedViaOemInternal() { 4526 Boolean isSatelliteSupported = getIsSatelliteSupported(); 4527 if (isSatelliteSupported != null) { 4528 /* We have already successfully queried the satellite modem. */ 4529 return isSatelliteSupported; 4530 } 4531 4532 /** 4533 * We have not successfully checked whether the modem supports satellite service. 4534 * Thus, we need to retry it now. 4535 */ 4536 requestIsSatelliteSupported( 4537 new ResultReceiver(this) { 4538 @Override 4539 protected void onReceiveResult(int resultCode, Bundle resultData) { 4540 decrementResultReceiverCount( 4541 "SC:isSatelliteSupportedViaOemInternal"); 4542 plogd("isSatelliteSupportedViaOemInternal.requestIsSatelliteSupported:" 4543 + " resultCode=" + resultCode); 4544 } 4545 }); 4546 incrementResultReceiverCount("SC:isSatelliteSupportedViaOemInternal"); 4547 return null; 4548 } 4549 handleEventProvisionSatelliteServiceDone( @onNull ProvisionSatelliteServiceArgument arg, @SatelliteManager.SatelliteResult int result)4550 private void handleEventProvisionSatelliteServiceDone( 4551 @NonNull ProvisionSatelliteServiceArgument arg, 4552 @SatelliteManager.SatelliteResult int result) { 4553 plogd("handleEventProvisionSatelliteServiceDone: result=" 4554 + result + ", subId=" + arg.subId); 4555 4556 Consumer<Integer> callback = mSatelliteProvisionCallbacks.remove(arg.subId); 4557 if (callback == null) { 4558 ploge("handleEventProvisionSatelliteServiceDone: callback is null for subId=" 4559 + arg.subId); 4560 mProvisionMetricsStats 4561 .setResultCode(SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE) 4562 .setIsProvisionRequest(true) 4563 .setCarrierId(getSatelliteCarrierId()) 4564 .setIsNtnOnlyCarrier(isNtnOnlyCarrier()) 4565 .reportProvisionMetrics(); 4566 mControllerMetricsStats.reportProvisionCount( 4567 SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE); 4568 return; 4569 } 4570 if (result == SATELLITE_RESULT_SUCCESS 4571 || result == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) { 4572 persistOemEnabledSatelliteProvisionStatus(true); 4573 callback.accept(SATELLITE_RESULT_SUCCESS); 4574 updateCachedDeviceProvisionStatus(); 4575 } else { 4576 callback.accept(result); 4577 } 4578 mProvisionMetricsStats.setResultCode(result) 4579 .setIsProvisionRequest(true) 4580 .setCarrierId(getSatelliteCarrierId()) 4581 .setIsNtnOnlyCarrier(isNtnOnlyCarrier()) 4582 .reportProvisionMetrics(); 4583 mControllerMetricsStats.reportProvisionCount(result); 4584 } 4585 handleEventDeprovisionSatelliteServiceDone( @onNull ProvisionSatelliteServiceArgument arg, @SatelliteManager.SatelliteResult int result)4586 private void handleEventDeprovisionSatelliteServiceDone( 4587 @NonNull ProvisionSatelliteServiceArgument arg, 4588 @SatelliteManager.SatelliteResult int result) { 4589 if (arg == null) { 4590 ploge("handleEventDeprovisionSatelliteServiceDone: arg is null"); 4591 return; 4592 } 4593 plogd("handleEventDeprovisionSatelliteServiceDone: result=" 4594 + result + ", subId=" + arg.subId); 4595 4596 if (result == SATELLITE_RESULT_SUCCESS 4597 || result == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) { 4598 persistOemEnabledSatelliteProvisionStatus(false); 4599 if (arg.callback != null) { 4600 arg.callback.accept(SATELLITE_RESULT_SUCCESS); 4601 } 4602 updateCachedDeviceProvisionStatus(); 4603 } else if (arg.callback != null) { 4604 arg.callback.accept(result); 4605 } 4606 mProvisionMetricsStats.setResultCode(result) 4607 .setIsProvisionRequest(false) 4608 .setCarrierId(getSatelliteCarrierId()) 4609 .setIsNtnOnlyCarrier(isNtnOnlyCarrier()) 4610 .reportProvisionMetrics(); 4611 mControllerMetricsStats.reportDeprovisionCount(result); 4612 } 4613 handleStartSatelliteTransmissionUpdatesDone(@onNull AsyncResult ar)4614 private void handleStartSatelliteTransmissionUpdatesDone(@NonNull AsyncResult ar) { 4615 SatelliteControllerHandlerRequest request = (SatelliteControllerHandlerRequest) ar.userObj; 4616 SatelliteTransmissionUpdateArgument arg = 4617 (SatelliteTransmissionUpdateArgument) request.argument; 4618 int errorCode = SatelliteServiceUtils.getSatelliteError(ar, 4619 "handleStartSatelliteTransmissionUpdatesDone"); 4620 arg.errorCallback.accept(errorCode); 4621 4622 if (errorCode != SATELLITE_RESULT_SUCCESS) { 4623 mPointingAppController.setStartedSatelliteTransmissionUpdates(false); 4624 // We need to remove the callback from our listener list since the caller might not call 4625 // stopSatelliteTransmissionUpdates to unregister the callback in case of failure. 4626 mPointingAppController.unregisterForSatelliteTransmissionUpdates(arg.subId, 4627 arg.errorCallback, arg.callback); 4628 } else { 4629 mPointingAppController.setStartedSatelliteTransmissionUpdates(true); 4630 } 4631 } 4632 4633 /** 4634 * Posts the specified command to be executed on the main thread and returns immediately. 4635 * 4636 * @param command command to be executed on the main thread 4637 * @param argument additional parameters required to perform of the operation 4638 * @param phone phone object used to perform the operation. 4639 */ sendRequestAsync(int command, @NonNull Object argument, @Nullable Phone phone)4640 private void sendRequestAsync(int command, @NonNull Object argument, @Nullable Phone phone) { 4641 SatelliteControllerHandlerRequest request = new SatelliteControllerHandlerRequest( 4642 argument, phone); 4643 Message msg = this.obtainMessage(command, request); 4644 msg.sendToTarget(); 4645 } 4646 4647 /** 4648 * Check if satellite is provisioned for the device. 4649 * @return {@code true} if device is provisioned for satellite else return {@code false}. 4650 */ 4651 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) 4652 @Nullable isDeviceProvisioned()4653 protected Boolean isDeviceProvisioned() { 4654 synchronized (mDeviceProvisionLock) { 4655 if (mOverriddenIsSatelliteViaOemProvisioned != null) { 4656 return mOverriddenIsSatelliteViaOemProvisioned; 4657 } 4658 4659 if (mIsDeviceProvisioned == null) { 4660 mIsDeviceProvisioned = getPersistedDeviceProvisionStatus(); 4661 } 4662 return mIsDeviceProvisioned; 4663 } 4664 } 4665 handleSatelliteEnabled(SatelliteControllerHandlerRequest request)4666 private void handleSatelliteEnabled(SatelliteControllerHandlerRequest request) { 4667 RequestSatelliteEnabledArgument argument = 4668 (RequestSatelliteEnabledArgument) request.argument; 4669 handlePersistentLoggingOnSessionStart(argument); 4670 selectBindingSatelliteSubscription(false); 4671 SatelliteModemEnableRequestAttributes enableRequestAttributes = 4672 createModemEnableRequest(argument); 4673 if (enableRequestAttributes == null) { 4674 plogw("handleSatelliteEnabled: enableRequestAttributes is null"); 4675 sendErrorAndReportSessionMetrics( 4676 SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE, argument.callback); 4677 synchronized (mSatelliteEnabledRequestLock) { 4678 if (argument.enableSatellite) { 4679 mSatelliteEnabledRequest = null; 4680 } else { 4681 mSatelliteDisabledRequest = null; 4682 } 4683 } 4684 return; 4685 } 4686 4687 if (mSatelliteSessionController != null) { 4688 mSatelliteSessionController.onSatelliteEnablementStarted(argument.enableSatellite); 4689 } else { 4690 ploge("handleSatelliteEnabled: mSatelliteSessionController is not initialized yet"); 4691 } 4692 4693 /* Framework will send back the disable result to the requesting client only after receiving 4694 * both confirmation for the disable request from modem, and OFF state from modem if the 4695 * modem is not in OFF state. 4696 */ 4697 if (!argument.enableSatellite && mSatelliteModemInterface.isSatelliteServiceSupported()) { 4698 synchronized (mSatelliteEnabledRequestLock) { 4699 mWaitingForDisableSatelliteModemResponse = true; 4700 if (!isSatelliteDisabled()) mWaitingForSatelliteModemOff = true; 4701 } 4702 } 4703 4704 Message onCompleted = obtainMessage(EVENT_SET_SATELLITE_ENABLED_DONE, request); 4705 mSatelliteModemInterface.requestSatelliteEnabled( 4706 enableRequestAttributes, onCompleted); 4707 startWaitForSatelliteEnablingResponseTimer(argument); 4708 // Logs satellite session timestamps for session metrics 4709 if (argument.enableSatellite) { 4710 mSessionStartTimeStamp = getElapsedRealtime(); 4711 } 4712 mSessionProcessingTimeStamp = getElapsedRealtime(); 4713 } 4714 4715 /** Get the request attributes that modem needs to enable/disable satellite */ createModemEnableRequest( @onNull RequestSatelliteEnabledArgument arg)4716 @Nullable private SatelliteModemEnableRequestAttributes createModemEnableRequest( 4717 @NonNull RequestSatelliteEnabledArgument arg) { 4718 int subId = getSelectedSatelliteSubId(); 4719 SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(subId); 4720 if (subInfo == null) { 4721 loge("createModemEnableRequest: no SubscriptionInfo found for subId=" + subId); 4722 return null; 4723 } 4724 String iccid = subInfo.getIccId(); 4725 String apn = getNiddApnName(subId); 4726 return new SatelliteModemEnableRequestAttributes( 4727 arg.enableSatellite, arg.enableDemoMode, arg.isEmergency, 4728 new SatelliteSubscriptionInfo(iccid, apn)); 4729 } 4730 getNiddApnName(int subId)4731 @NonNull private String getNiddApnName(int subId) { 4732 if (SatelliteServiceUtils.isNtnOnlySubscriptionId(subId)) { 4733 String apn = mContext.getResources().getString(R.string.config_satellite_nidd_apn_name); 4734 if (!TextUtils.isEmpty(apn)) { 4735 return apn; 4736 } 4737 } 4738 return getConfigForSubId(subId).getString(KEY_SATELLITE_NIDD_APN_NAME_STRING, ""); 4739 } 4740 handleRequestSatelliteAttachRestrictionForCarrierCmd( SatelliteControllerHandlerRequest request)4741 private void handleRequestSatelliteAttachRestrictionForCarrierCmd( 4742 SatelliteControllerHandlerRequest request) { 4743 RequestHandleSatelliteAttachRestrictionForCarrierArgument argument = 4744 (RequestHandleSatelliteAttachRestrictionForCarrierArgument) request.argument; 4745 4746 if (argument.reason == SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER) { 4747 if (!persistSatelliteAttachEnabledForCarrierSetting(argument.subId)) { 4748 argument.callback.accept(SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE); 4749 return; 4750 } 4751 } 4752 4753 evaluateEnablingSatelliteForCarrier(argument.subId, argument.reason, argument.callback); 4754 } 4755 updateSatelliteSupportedState(boolean supported)4756 private void updateSatelliteSupportedState(boolean supported) { 4757 synchronized (mIsSatelliteSupportedLock) { 4758 mIsSatelliteSupported = supported; 4759 } 4760 mSatelliteSessionController = SatelliteSessionController.make( 4761 mContext, getLooper(), mFeatureFlags, supported); 4762 plogd("updateSatelliteSupportedState: create a new SatelliteSessionController because " 4763 + "satellite supported state has changed to " + supported); 4764 4765 if (supported) { 4766 registerForPendingDatagramCount(); 4767 registerForSatelliteModemStateChanged(); 4768 registerForNtnSignalStrengthChanged(); 4769 registerForCapabilitiesChanged(); 4770 registerForSatelliteRegistrationFailure(); 4771 registerForTerrestrialNetworkAvailableChanged(); 4772 4773 requestIsSatelliteProvisioned( 4774 new ResultReceiver(this) { 4775 @Override 4776 protected void onReceiveResult(int resultCode, Bundle resultData) { 4777 plogd("updateSatelliteSupportedState.requestIsSatelliteProvisioned: " 4778 + "resultCode=" + resultCode + ", resultData=" + resultData); 4779 decrementResultReceiverCount("SC:requestIsSatelliteProvisioned"); 4780 requestSatelliteEnabled(false, false, false, 4781 new IIntegerConsumer.Stub() { 4782 @Override 4783 public void accept(int result) { 4784 plogd("updateSatelliteSupportedState." 4785 + "requestSatelliteEnabled: result=" + result); 4786 } 4787 }); 4788 } 4789 }); 4790 incrementResultReceiverCount("SC:requestIsSatelliteProvisioned"); 4791 4792 requestSatelliteCapabilities( 4793 new ResultReceiver(this) { 4794 @Override 4795 protected void onReceiveResult(int resultCode, Bundle resultData) { 4796 plogd("updateSatelliteSupportedState.requestSatelliteCapabilities: " 4797 + "resultCode=" + resultCode + ", resultData=" + resultData); 4798 decrementResultReceiverCount("SC:requestSatelliteCapabilities"); 4799 } 4800 }); 4801 incrementResultReceiverCount("SC:requestSatelliteCapabilities"); 4802 } 4803 registerForSatelliteSupportedStateChanged(); 4804 selectBindingSatelliteSubscription(false); 4805 notifySatelliteSupportedStateChanged(supported); 4806 } 4807 updateSatelliteEnabledState(boolean enabled, String caller)4808 private void updateSatelliteEnabledState(boolean enabled, String caller) { 4809 synchronized (mIsSatelliteEnabledLock) { 4810 mIsSatelliteEnabled = enabled; 4811 } 4812 if (mSatelliteSessionController != null) { 4813 mSatelliteSessionController.onSatelliteEnabledStateChanged(enabled); 4814 mSatelliteSessionController.setDemoMode(mIsDemoModeEnabled); 4815 } else { 4816 ploge(caller + ": mSatelliteSessionController is not initialized yet"); 4817 } 4818 if (!enabled) { 4819 mIsModemEnabledReportingNtnSignalStrength.set(false); 4820 } 4821 if (mFeatureFlags.satelliteStateChangeListener()) { 4822 notifyEnabledStateChanged(enabled); 4823 } 4824 } 4825 registerForPendingDatagramCount()4826 private void registerForPendingDatagramCount() { 4827 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 4828 if (!mRegisteredForPendingDatagramCountWithSatelliteService.get()) { 4829 mSatelliteModemInterface.registerForPendingDatagrams( 4830 this, EVENT_PENDING_DATAGRAMS, null); 4831 mRegisteredForPendingDatagramCountWithSatelliteService.set(true); 4832 } 4833 } 4834 } 4835 registerForSatelliteModemStateChanged()4836 private void registerForSatelliteModemStateChanged() { 4837 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 4838 if (!mRegisteredForSatelliteModemStateChangedWithSatelliteService.get()) { 4839 mSatelliteModemInterface.registerForSatelliteModemStateChanged( 4840 this, EVENT_SATELLITE_MODEM_STATE_CHANGED, null); 4841 mRegisteredForSatelliteModemStateChangedWithSatelliteService.set(true); 4842 } 4843 } 4844 } 4845 registerForNtnSignalStrengthChanged()4846 private void registerForNtnSignalStrengthChanged() { 4847 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 4848 if (!mRegisteredForNtnSignalStrengthChanged.get()) { 4849 mSatelliteModemInterface.registerForNtnSignalStrengthChanged( 4850 this, EVENT_NTN_SIGNAL_STRENGTH_CHANGED, null); 4851 mRegisteredForNtnSignalStrengthChanged.set(true); 4852 } 4853 } 4854 } 4855 registerForCapabilitiesChanged()4856 private void registerForCapabilitiesChanged() { 4857 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 4858 if (!mRegisteredForSatelliteCapabilitiesChanged.get()) { 4859 mSatelliteModemInterface.registerForSatelliteCapabilitiesChanged( 4860 this, EVENT_SATELLITE_CAPABILITIES_CHANGED, null); 4861 mRegisteredForSatelliteCapabilitiesChanged.set(true); 4862 } 4863 } 4864 } 4865 registerForSatelliteSupportedStateChanged()4866 private void registerForSatelliteSupportedStateChanged() { 4867 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 4868 if (!mRegisteredForSatelliteSupportedStateChanged.get()) { 4869 mSatelliteModemInterface.registerForSatelliteSupportedStateChanged( 4870 this, EVENT_SATELLITE_SUPPORTED_STATE_CHANGED, null); 4871 mRegisteredForSatelliteSupportedStateChanged.set(true); 4872 } 4873 } 4874 } 4875 registerForSatelliteRegistrationFailure()4876 private void registerForSatelliteRegistrationFailure() { 4877 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 4878 if (!mRegisteredForSatelliteRegistrationFailure.get()) { 4879 mSatelliteModemInterface.registerForSatelliteRegistrationFailure(this, 4880 EVENT_SATELLITE_REGISTRATION_FAILURE, null); 4881 mRegisteredForSatelliteRegistrationFailure.set(true); 4882 } 4883 } 4884 } 4885 registerForTerrestrialNetworkAvailableChanged()4886 private void registerForTerrestrialNetworkAvailableChanged() { 4887 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 4888 if (!mRegisteredForTerrestrialNetworkAvailableChanged.get()) { 4889 mSatelliteModemInterface.registerForTerrestrialNetworkAvailableChanged(this, 4890 EVENT_TERRESTRIAL_NETWORK_AVAILABLE_CHANGED, null); 4891 mRegisteredForTerrestrialNetworkAvailableChanged.set(true); 4892 } 4893 } 4894 } 4895 notifyDeviceProvisionStateChanged(boolean provisioned)4896 private void notifyDeviceProvisionStateChanged(boolean provisioned) { 4897 List<ISatelliteProvisionStateCallback> deadCallersList = new ArrayList<>(); 4898 mSatelliteProvisionStateChangedListeners.values().forEach(listener -> { 4899 try { 4900 listener.onSatelliteProvisionStateChanged(provisioned); 4901 } catch (RemoteException e) { 4902 plogd("notifyDeviceProvisionStateChanged RemoteException: " + e); 4903 deadCallersList.add(listener); 4904 } 4905 }); 4906 deadCallersList.forEach(listener -> { 4907 mSatelliteProvisionStateChangedListeners.remove(listener.asBinder()); 4908 }); 4909 } 4910 updateSatelliteSubscriptionProvisionState(List<SatelliteSubscriberInfo> newList, boolean provisioned)4911 private boolean updateSatelliteSubscriptionProvisionState(List<SatelliteSubscriberInfo> newList, 4912 boolean provisioned) { 4913 logd("updateSatelliteSubscriptionProvisionState: List=" + newList + " , provisioned=" 4914 + provisioned); 4915 boolean provisionChanged = false; 4916 synchronized (mSatelliteTokenProvisionedLock) { 4917 for (SatelliteSubscriberInfo subscriberInfo : newList) { 4918 4919 int subId = subscriberInfo.getSubscriptionId(); 4920 Boolean currentProvisioned = 4921 mProvisionedSubscriberId.get(subscriberInfo.getSubscriberId()); 4922 if (currentProvisioned == null) { 4923 currentProvisioned = false; 4924 } 4925 4926 Boolean isProvisionedInPersistentDb = false; 4927 try { 4928 isProvisionedInPersistentDb = mSubscriptionManagerService 4929 .isSatelliteProvisionedForNonIpDatagram(subId); 4930 if (isProvisionedInPersistentDb == null) { 4931 isProvisionedInPersistentDb = false; 4932 } 4933 } catch (IllegalArgumentException | SecurityException ex) { 4934 ploge("isSatelliteProvisionedForNonIpDatagram: subId=" + subId + ", ex=" 4935 + ex); 4936 } 4937 if (currentProvisioned == provisioned 4938 && isProvisionedInPersistentDb == provisioned) { 4939 continue; 4940 } 4941 provisionChanged = true; 4942 mProvisionedSubscriberId.put(subscriberInfo.getSubscriberId(), provisioned); 4943 try { 4944 mSubscriptionManagerService.setIsSatelliteProvisionedForNonIpDatagram(subId, 4945 provisioned); 4946 plogd("updateSatelliteSubscriptionProvisionState: set Provision state to db " 4947 + "subId=" + subId); 4948 } catch (IllegalArgumentException | SecurityException ex) { 4949 ploge("setIsSatelliteProvisionedForNonIpDatagram: subId=" + subId + ", ex=" 4950 + ex); 4951 } 4952 } 4953 } 4954 return provisionChanged; 4955 } 4956 handleEventSatelliteSubscriptionProvisionStateChanged()4957 private void handleEventSatelliteSubscriptionProvisionStateChanged() { 4958 List<SatelliteSubscriberProvisionStatus> informList = 4959 getPrioritizedSatelliteSubscriberProvisionStatusList(); 4960 plogd("handleEventSatelliteSubscriptionProvisionStateChanged: " + informList); 4961 notifySatelliteSubscriptionProvisionStateChanged(informList); 4962 updateCachedDeviceProvisionStatus(); 4963 // Report updated provisioned status to metrics. 4964 synchronized (mSatelliteTokenProvisionedLock) { 4965 boolean isProvisioned = !mProvisionedSubscriberId.isEmpty() 4966 && mProvisionedSubscriberId.containsValue(Boolean.TRUE); 4967 mControllerMetricsStats.setIsProvisioned(isProvisioned); 4968 } 4969 selectBindingSatelliteSubscription(false); 4970 evaluateCarrierRoamingNtnEligibilityChange(); 4971 } 4972 updateCachedDeviceProvisionStatus()4973 private void updateCachedDeviceProvisionStatus() { 4974 boolean isProvisioned = getPersistedDeviceProvisionStatus(); 4975 plogd("updateCachedDeviceProvisionStatus: isProvisioned=" + isProvisioned); 4976 synchronized (mDeviceProvisionLock) { 4977 if (mIsDeviceProvisioned == null || mIsDeviceProvisioned != isProvisioned) { 4978 mIsDeviceProvisioned = isProvisioned; 4979 notifyDeviceProvisionStateChanged(isProvisioned); 4980 } 4981 } 4982 } 4983 notifySatelliteSubscriptionProvisionStateChanged( @onNull List<SatelliteSubscriberProvisionStatus> list)4984 private void notifySatelliteSubscriptionProvisionStateChanged( 4985 @NonNull List<SatelliteSubscriberProvisionStatus> list) { 4986 List<ISatelliteProvisionStateCallback> deadCallersList = new ArrayList<>(); 4987 mSatelliteProvisionStateChangedListeners.values().forEach(listener -> { 4988 try { 4989 listener.onSatelliteSubscriptionProvisionStateChanged(list); 4990 } catch (RemoteException e) { 4991 plogd("notifySatelliteSubscriptionProvisionStateChanged: " + e); 4992 deadCallersList.add(listener); 4993 } 4994 }); 4995 deadCallersList.forEach(listener -> { 4996 mSatelliteProvisionStateChangedListeners.remove(listener.asBinder()); 4997 }); 4998 } 4999 handleEventSatelliteModemStateChanged( @atelliteManager.SatelliteModemState int state)5000 private void handleEventSatelliteModemStateChanged( 5001 @SatelliteManager.SatelliteModemState int state) { 5002 plogd("handleEventSatelliteModemStateChanged: state=" + state); 5003 5004 synchronized (mSatelliteModemStateLock) { 5005 mSatelliteModemState = state; 5006 } 5007 5008 if (state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE 5009 || state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) { 5010 if (!isWaitingForDisableSatelliteModemResponse()) { 5011 moveSatelliteToOffStateAndCleanUpResources(SATELLITE_RESULT_SUCCESS); 5012 } else { 5013 notifyModemStateChangedToSessionController( 5014 SatelliteManager.SATELLITE_MODEM_STATE_OFF); 5015 } 5016 5017 synchronized (mSatelliteEnabledRequestLock) { 5018 mWaitingForSatelliteModemOff = false; 5019 } 5020 } else { 5021 if (isSatelliteEnabledOrBeingEnabled() || isSatelliteBeingDisabled()) { 5022 notifyModemStateChangedToSessionController(state); 5023 } else { 5024 // Telephony framework and modem are out of sync. We need to disable 5025 synchronized (mSatelliteEnabledRequestLock) { 5026 plogw("Satellite modem is in a bad state. Disabling satellite modem now ..."); 5027 Consumer<Integer> result = integer -> plogd( 5028 "handleEventSatelliteModemStateChanged: disabling satellite result=" 5029 + integer); 5030 mSatelliteDisabledRequest = new RequestSatelliteEnabledArgument( 5031 false /* enableSatellite */, false /* enableDemoMode */, 5032 false /* isEmergency */, result); 5033 sendRequestAsync(CMD_SET_SATELLITE_ENABLED, mSatelliteDisabledRequest, null); 5034 } 5035 } 5036 } 5037 } 5038 notifyModemStateChangedToSessionController( @atelliteManager.SatelliteModemState int state)5039 private void notifyModemStateChangedToSessionController( 5040 @SatelliteManager.SatelliteModemState int state) { 5041 if (mSatelliteSessionController != null) { 5042 mSatelliteSessionController.onSatelliteModemStateChanged(state); 5043 } else { 5044 ploge("notifyModemStateChangedToSessionController: mSatelliteSessionController is " 5045 + "null"); 5046 } 5047 } 5048 handleEventNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength)5049 private void handleEventNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) { 5050 logd("handleEventNtnSignalStrengthChanged: ntnSignalStrength=" + ntnSignalStrength); 5051 synchronized (mNtnSignalsStrengthLock) { 5052 mNtnSignalStrength = ntnSignalStrength; 5053 } 5054 mSessionMetricsStats.updateMaxNtnSignalStrengthLevel(ntnSignalStrength.getLevel()); 5055 5056 List<INtnSignalStrengthCallback> deadCallersList = new ArrayList<>(); 5057 mNtnSignalStrengthChangedListeners.values().forEach(listener -> { 5058 try { 5059 listener.onNtnSignalStrengthChanged(ntnSignalStrength); 5060 } catch (RemoteException e) { 5061 plogd("handleEventNtnSignalStrengthChanged RemoteException: " + e); 5062 deadCallersList.add(listener); 5063 } 5064 }); 5065 deadCallersList.forEach(listener -> { 5066 mNtnSignalStrengthChangedListeners.remove(listener.asBinder()); 5067 }); 5068 } 5069 handleEventSatelliteCapabilitiesChanged(SatelliteCapabilities capabilities)5070 private void handleEventSatelliteCapabilitiesChanged(SatelliteCapabilities capabilities) { 5071 plogd("handleEventSatelliteCapabilitiesChanged()"); 5072 5073 synchronized (mSatelliteCapabilitiesLock) { 5074 mSatelliteCapabilities = capabilities; 5075 } 5076 overrideSatelliteCapabilitiesIfApplicable(); 5077 5078 SatelliteCapabilities satelliteCapabilities = getSatelliteCapabilities(); 5079 List<ISatelliteCapabilitiesCallback> deadCallersList = new ArrayList<>(); 5080 mSatelliteCapabilitiesChangedListeners.values().forEach(listener -> { 5081 try { 5082 listener.onSatelliteCapabilitiesChanged(satelliteCapabilities); 5083 } catch (RemoteException e) { 5084 plogd("handleEventSatelliteCapabilitiesChanged RemoteException: " + e); 5085 deadCallersList.add(listener); 5086 } 5087 }); 5088 deadCallersList.forEach(listener -> { 5089 mSatelliteCapabilitiesChangedListeners.remove(listener.asBinder()); 5090 }); 5091 } 5092 handleEventSatelliteSupportedStateChanged(boolean supported)5093 private void handleEventSatelliteSupportedStateChanged(boolean supported) { 5094 plogd("handleSatelliteSupportedStateChangedEvent: supported=" + supported); 5095 5096 Boolean isSatelliteSupported = getIsSatelliteSupported(); 5097 if (isSatelliteSupported != null && isSatelliteSupported == supported) { 5098 if (DBG) { 5099 plogd("current satellite support state and new supported state are matched," 5100 + " ignore update."); 5101 } 5102 return; 5103 } 5104 5105 updateSatelliteSupportedState(supported); 5106 5107 Boolean isSatelliteEnabled = getIsSatelliteEnabled(); 5108 /* In case satellite has been reported as not support from modem, but satellite is 5109 enabled, request disable satellite. */ 5110 if (!supported && isSatelliteEnabled != null && isSatelliteEnabled) { 5111 plogd("Invoke requestSatelliteEnabled(), supported=false, " 5112 + "mIsSatelliteEnabled=true"); 5113 requestSatelliteEnabled(false /* enableSatellite */, false /* enableDemoMode */, 5114 false /* isEmergency */, 5115 new IIntegerConsumer.Stub() { 5116 @Override 5117 public void accept(int result) { 5118 plogd("handleSatelliteSupportedStateChangedEvent: request " 5119 + "satellite disable, result=" + result); 5120 } 5121 }); 5122 5123 } 5124 5125 synchronized (mIsSatelliteSupportedLock) { 5126 mIsSatelliteSupported = supported; 5127 } 5128 } 5129 handleEventSelectedNbIotSatelliteSubscriptionChanged(int selectedSubId)5130 private void handleEventSelectedNbIotSatelliteSubscriptionChanged(int selectedSubId) { 5131 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 5132 plogd("handleEventSelectedNbIotSatelliteSubscriptionChanged: " 5133 + "carrierRoamingNbIotNtn flag is disabled"); 5134 return; 5135 } 5136 5137 plogd("handleEventSelectedNbIotSatelliteSubscriptionChanged: " + selectedSubId); 5138 5139 List<ISelectedNbIotSatelliteSubscriptionCallback> deadCallersList = new ArrayList<>(); 5140 mSelectedNbIotSatelliteSubscriptionChangedListeners.values().forEach(listener -> { 5141 try { 5142 listener.onSelectedNbIotSatelliteSubscriptionChanged(selectedSubId); 5143 } catch (RemoteException e) { 5144 logd("handleEventSelectedNbIotSatelliteSubscriptionChanged RemoteException: " + e); 5145 deadCallersList.add(listener); 5146 } 5147 }); 5148 deadCallersList.forEach(listener -> { 5149 mSelectedNbIotSatelliteSubscriptionChangedListeners.remove(listener.asBinder()); 5150 }); 5151 } 5152 notifySatelliteSupportedStateChanged(boolean supported)5153 private void notifySatelliteSupportedStateChanged(boolean supported) { 5154 List<IBooleanConsumer> deadCallersList = new ArrayList<>(); 5155 mSatelliteSupportedStateChangedListeners.values().forEach(listener -> { 5156 try { 5157 listener.accept(supported); 5158 } catch (RemoteException e) { 5159 plogd("handleSatelliteSupportedStateChangedEvent RemoteException: " + e); 5160 deadCallersList.add(listener); 5161 } 5162 }); 5163 deadCallersList.forEach(listener -> { 5164 mSatelliteSupportedStateChangedListeners.remove(listener.asBinder()); 5165 }); 5166 } 5167 5168 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) setSettingsKeyForSatelliteMode(int val)5169 protected void setSettingsKeyForSatelliteMode(int val) { 5170 plogd("setSettingsKeyForSatelliteMode val: " + val); 5171 Settings.Global.putInt(mContext.getContentResolver(), 5172 Settings.Global.SATELLITE_MODE_ENABLED, val); 5173 } 5174 5175 /** 5176 * Allow screen rotation temporary in rotation locked foldable device. 5177 * <p> 5178 * Temporarily allow screen rotation user to catch satellite signals properly by UI guide in 5179 * emergency situations. Unlock the setting value so that the screen rotation is not locked, and 5180 * return it to the original value when the satellite service is finished. 5181 * <p> 5182 * Note that, only the unfolded screen will be temporarily allowed screen rotation. 5183 * 5184 * @param val {@link SATELLITE_MODE_ENABLED_TRUE} if satellite mode is enabled, 5185 * {@link SATELLITE_MODE_ENABLED_FALSE} satellite mode is not enabled. 5186 */ 5187 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) setSettingsKeyToAllowDeviceRotation(int val)5188 protected void setSettingsKeyToAllowDeviceRotation(int val) { 5189 // Only allows on a foldable device type. 5190 if (!isFoldable(mContext, mDeviceStates)) { 5191 logd("setSettingsKeyToAllowDeviceRotation(" + val + "), device was not a foldable"); 5192 return; 5193 } 5194 5195 switch (val) { 5196 case SATELLITE_MODE_ENABLED_TRUE: 5197 mDeviceRotationLockToBackupAndRestore = 5198 Settings.Secure.getString(mContentResolver, 5199 Settings.Secure.DEVICE_STATE_ROTATION_LOCK); 5200 String unlockedRotationSettings = replaceDeviceRotationValue( 5201 mDeviceRotationLockToBackupAndRestore == null 5202 ? "" : mDeviceRotationLockToBackupAndRestore, 5203 Settings.Secure.DEVICE_STATE_ROTATION_KEY_UNFOLDED, 5204 Settings.Secure.DEVICE_STATE_ROTATION_LOCK_UNLOCKED); 5205 Settings.Secure.putString(mContentResolver, 5206 Settings.Secure.DEVICE_STATE_ROTATION_LOCK, unlockedRotationSettings); 5207 logd("setSettingsKeyToAllowDeviceRotation(TRUE), RotationSettings is changed" 5208 + " from " + mDeviceRotationLockToBackupAndRestore 5209 + " to " + unlockedRotationSettings); 5210 break; 5211 case SATELLITE_MODE_ENABLED_FALSE: 5212 if (mDeviceRotationLockToBackupAndRestore == null) { 5213 break; 5214 } 5215 Settings.Secure.putString(mContentResolver, 5216 Settings.Secure.DEVICE_STATE_ROTATION_LOCK, 5217 mDeviceRotationLockToBackupAndRestore); 5218 logd("setSettingsKeyToAllowDeviceRotation(FALSE), RotationSettings is restored to" 5219 + mDeviceRotationLockToBackupAndRestore); 5220 mDeviceRotationLockToBackupAndRestore = ""; 5221 break; 5222 default: 5223 loge("setSettingsKeyToAllowDeviceRotation(" + val + "), never reach here."); 5224 break; 5225 } 5226 } 5227 5228 /** 5229 * If the device type is foldable. 5230 * 5231 * @param context context 5232 * @param deviceStates list of {@link DeviceState}s provided from {@link DeviceStateManager} 5233 * @return {@code true} if device type is foldable. {@code false} for otherwise. 5234 */ 5235 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) isFoldable(Context context, List<DeviceState> deviceStates)5236 public boolean isFoldable(Context context, List<DeviceState> deviceStates) { 5237 if (android.hardware.devicestate.feature.flags.Flags.deviceStatePropertyMigration()) { 5238 return deviceStates.stream().anyMatch(deviceState -> deviceState.hasProperty( 5239 PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY) 5240 || deviceState.hasProperty( 5241 PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY)); 5242 } else { 5243 return context.getResources().getIntArray(R.array.config_foldedDeviceStates).length > 0; 5244 } 5245 } 5246 5247 /** 5248 * Replaces a value of given a target key with a new value in a string of key-value pairs. 5249 * <p> 5250 * Replaces the value corresponding to the target key with a new value. If the key value is not 5251 * found in the device rotation information, it is not replaced. 5252 * 5253 * @param deviceRotationValue Device rotation key values separated by colon(':'). 5254 * @param targetKey The key of the new item caller wants to add. 5255 * @param newValue The value of the new item caller want to add. 5256 * @return A new string where all the key-value pairs. 5257 */ replaceDeviceRotationValue( @onNull String deviceRotationValue, int targetKey, int newValue)5258 private static String replaceDeviceRotationValue( 5259 @NonNull String deviceRotationValue, int targetKey, int newValue) { 5260 // Use list of Key-Value pair 5261 List<Pair<Integer, Integer>> keyValuePairs = new ArrayList<>(); 5262 5263 String[] pairs = deviceRotationValue.split(":"); 5264 if (pairs.length % 2 != 0) { 5265 // Return without modifying. The key-value may be incorrect if length is an odd number. 5266 loge("The length of key-value pair do not match. Return without modification."); 5267 return deviceRotationValue; 5268 } 5269 5270 // collect into keyValuePairs 5271 for (int i = 0; i < pairs.length; i += 2) { 5272 try { 5273 int key = Integer.parseInt(pairs[i]); 5274 int value = Integer.parseInt(pairs[i + 1]); 5275 keyValuePairs.add(new Pair<>(key, key == targetKey ? newValue : value)); 5276 } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { 5277 // Return without modifying if got exception. 5278 loge("got error while parsing key-value. Return without modification. e:" + e); 5279 return deviceRotationValue; 5280 } 5281 } 5282 5283 return keyValuePairs.stream() 5284 .map(pair -> pair.first + ":" + pair.second) // Convert to "key:value" format 5285 .collect(Collectors.joining(":")); // Join pairs with colons 5286 } 5287 5288 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) areAllRadiosDisabled()5289 protected boolean areAllRadiosDisabled() { 5290 synchronized (mRadioStateLock) { 5291 if ((mDisableBTOnSatelliteEnabled && mBTStateEnabled) 5292 || (mDisableNFCOnSatelliteEnabled && mNfcStateEnabled) 5293 || (mDisableWifiOnSatelliteEnabled && mWifiStateEnabled) 5294 || (mDisableUWBOnSatelliteEnabled && mUwbStateEnabled)) { 5295 plogd("All radios are not disabled yet."); 5296 return false; 5297 } 5298 plogd("All radios are disabled."); 5299 return true; 5300 } 5301 } 5302 evaluateToSendSatelliteEnabledSuccess()5303 private void evaluateToSendSatelliteEnabledSuccess() { 5304 plogd("evaluateToSendSatelliteEnabledSuccess"); 5305 synchronized (mSatelliteEnabledRequestLock) { 5306 if (areAllRadiosDisabled() && (mSatelliteEnabledRequest != null) 5307 && mWaitingForRadioDisabled) { 5308 plogd("Sending success to callback that sent enable satellite request"); 5309 synchronized (mIsSatelliteEnabledLock) { 5310 mIsSatelliteEnabled = mSatelliteEnabledRequest.enableSatellite; 5311 } 5312 mSatelliteEnabledRequest.callback.accept(SATELLITE_RESULT_SUCCESS); 5313 updateSatelliteEnabledState( 5314 mSatelliteEnabledRequest.enableSatellite, 5315 "EVENT_SET_SATELLITE_ENABLED_DONE"); 5316 setEmergencyMode(mSatelliteEnabledRequest.isEmergency); 5317 if (mSatelliteEnabledRequest.enableSatellite 5318 && !mSatelliteEnabledRequest.isEmergency) { 5319 plogd("Starting pointingUI needFullscreenPointingUI=" + true 5320 + "mIsDemoModeEnabled=" + mIsDemoModeEnabled + ", isEmergency=" 5321 + mSatelliteEnabledRequest.isEmergency); 5322 mPointingAppController.startPointingUI(true, mIsDemoModeEnabled, false); 5323 } 5324 mSatelliteEnabledRequest = null; 5325 mWaitingForRadioDisabled = false; 5326 5327 if (mSatelliteEnableAttributesUpdateRequest != null) { 5328 sendRequestAsync(CMD_UPDATE_SATELLITE_ENABLE_ATTRIBUTES, 5329 mSatelliteEnableAttributesUpdateRequest, null); 5330 } 5331 updateLastNotifiedNtnModeAndNotify(getSatellitePhone()); 5332 5333 if (mFeatureFlags.satelliteExitP2pSessionOutsideGeofence()) { 5334 evaluateDisablingP2pSession(); 5335 } 5336 } 5337 } 5338 } 5339 resetSatelliteEnabledRequest()5340 private void resetSatelliteEnabledRequest() { 5341 plogd("resetSatelliteEnabledRequest"); 5342 synchronized (mSatelliteEnabledRequestLock) { 5343 mSatelliteEnabledRequest = null; 5344 mWaitingForRadioDisabled = false; 5345 } 5346 } 5347 resetSatelliteDisabledRequest()5348 private void resetSatelliteDisabledRequest() { 5349 plogd("resetSatelliteDisabledRequest"); 5350 synchronized (mSatelliteEnabledRequestLock) { 5351 mSatelliteDisabledRequest = null; 5352 mWaitingForDisableSatelliteModemResponse = false; 5353 mWaitingForSatelliteModemOff = false; 5354 } 5355 } 5356 5357 /** 5358 * Move to OFF state and clean up resources. 5359 * 5360 * @param resultCode The result code will be returned to requesting clients. 5361 */ 5362 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) moveSatelliteToOffStateAndCleanUpResources( @atelliteManager.SatelliteResult int resultCode)5363 public void moveSatelliteToOffStateAndCleanUpResources( 5364 @SatelliteManager.SatelliteResult int resultCode) { 5365 plogd("moveSatelliteToOffStateAndCleanUpResources"); 5366 setDemoModeEnabled(false); 5367 handlePersistentLoggingOnSessionEnd(mIsEmergency); 5368 setEmergencyMode(false); 5369 synchronized (mIsSatelliteEnabledLock) { 5370 mIsSatelliteEnabled = false; 5371 } 5372 setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_FALSE); 5373 setSettingsKeyToAllowDeviceRotation(SATELLITE_MODE_ENABLED_FALSE); 5374 abortSatelliteDisableRequest(resultCode); 5375 abortSatelliteEnableRequest(resultCode); 5376 abortSatelliteEnableAttributesUpdateRequest(resultCode); 5377 resetSatelliteEnabledRequest(); 5378 resetSatelliteDisabledRequest(); 5379 // TODO (b/361139260): Stop timer to wait for other radios off 5380 updateSatelliteEnabledState( 5381 false, "moveSatelliteToOffStateAndCleanUpResources"); 5382 selectBindingSatelliteSubscription(false); 5383 updateLastNotifiedNtnModeAndNotify(getSatellitePhone()); 5384 5385 sendMessage(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION)); 5386 // Evaluate eligibility after satellite session is disabled 5387 sendMessage(obtainMessage(CMD_EVALUATE_CARRIER_ROAMING_NTN_ELIGIBILITY_CHANGE)); 5388 } 5389 setDemoModeEnabled(boolean enabled)5390 private void setDemoModeEnabled(boolean enabled) { 5391 mIsDemoModeEnabled = enabled; 5392 mDatagramController.setDemoMode(mIsDemoModeEnabled); 5393 plogd("setDemoModeEnabled: mIsDemoModeEnabled=" + mIsDemoModeEnabled); 5394 } 5395 setEmergencyMode(boolean isEmergency)5396 private void setEmergencyMode(boolean isEmergency) { 5397 plogd("setEmergencyMode: mIsEmergency=" + mIsEmergency + ", isEmergency=" + isEmergency); 5398 if (mIsEmergency != isEmergency) { 5399 mIsEmergency = isEmergency; 5400 if (mSatelliteSessionController != null) { 5401 mSatelliteSessionController.onEmergencyModeChanged(mIsEmergency); 5402 } else { 5403 plogw("setEmergencyMode: mSatelliteSessionController is null"); 5404 } 5405 } 5406 } 5407 isMockModemAllowed()5408 private boolean isMockModemAllowed() { 5409 return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false)); 5410 } 5411 configureSatellitePlmnForCarrier(int subId)5412 private void configureSatellitePlmnForCarrier(int subId) { 5413 logd("configureSatellitePlmnForCarrier"); 5414 Phone phone = SatelliteServiceUtils.getPhone(subId); 5415 if (phone == null) { 5416 ploge("configureSatellitePlmnForCarrier: phone is null for subId=" + subId); 5417 return; 5418 } 5419 5420 List<String> allPlmnList = new ArrayList<>(getAllPlmnSet()); 5421 phone.setSatellitePlmn(phone.getPhoneId(), getCarrierPlmnList(subId), allPlmnList, 5422 obtainMessage(EVENT_SET_SATELLITE_PLMN_INFO_DONE)); 5423 } 5424 5425 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) getAllPlmnSet()5426 protected Set<String> getAllPlmnSet() { 5427 Set<String> allPlmnSetFromSubInfo = new HashSet<>(); 5428 int[] activeSubIdArray = mSubscriptionManagerService.getActiveSubIdList(true); 5429 for (int activeSubId : activeSubIdArray) { 5430 allPlmnSetFromSubInfo.addAll(getCarrierPlmnList(activeSubId)); 5431 allPlmnSetFromSubInfo.addAll(getBarredPlmnList(activeSubId)); 5432 } 5433 allPlmnSetFromSubInfo.addAll(mSatellitePlmnListFromOverlayConfig); 5434 5435 if (mIgnorePlmnListFromStorage.get()) { 5436 // Do not use PLMN list from storage 5437 plogd("getAllPlmnList: allPlmnSetFromSubInfo=" + allPlmnSetFromSubInfo); 5438 return allPlmnSetFromSubInfo; 5439 } 5440 5441 Set<String> allPlmnListFromStorage = getCarrierRoamingNtnAllSatellitePlmnSetFromStorage(); 5442 if (!allPlmnListFromStorage.containsAll(allPlmnSetFromSubInfo)) { 5443 allPlmnListFromStorage.addAll(allPlmnSetFromSubInfo); 5444 persistCarrierRoamingNtnAllSatellitePlmnSet(allPlmnListFromStorage); 5445 } 5446 5447 plogd("getAllPlmnList: " + allPlmnListFromStorage); 5448 return allPlmnListFromStorage; 5449 } 5450 getCarrierPlmnList(int subId)5451 private List<String> getCarrierPlmnList(int subId) { 5452 synchronized (mSupportedSatelliteServicesLock) { 5453 return mMergedPlmnListPerCarrier.get(subId, new ArrayList<>()).stream().toList(); 5454 } 5455 } 5456 getBarredPlmnList(int subId)5457 private List<String> getBarredPlmnList(int subId) { 5458 synchronized (mSupportedSatelliteServicesLock) { 5459 return mEntitlementBarredPlmnListPerCarrier.get( 5460 subId, new ArrayList<>()).stream().toList(); 5461 } 5462 } 5463 persistCarrierRoamingNtnAllSatellitePlmnSet(Set<String> allSatellitePlmnSet)5464 private void persistCarrierRoamingNtnAllSatellitePlmnSet(Set<String> allSatellitePlmnSet) { 5465 plogd("persistCarrierRoamingNtnAllSatellitePlmnSet"); 5466 if (!loadSatelliteSharedPreferences()) return; 5467 5468 if (mSharedPreferences == null) { 5469 ploge("persistCarrierRoamingNtnAllSatellitePlmnSet: mSharedPreferences is null"); 5470 } else { 5471 try { 5472 mSharedPreferences.edit().putStringSet( 5473 CARRIER_ROAMING_NTN_ALL_SATELLITE_PLMN_SET_KEY, allSatellitePlmnSet) 5474 .apply(); 5475 } catch (Exception ex) { 5476 plogd("persistCarrierRoamingNtnAllSatellitePlmnSet: ex=" + ex); 5477 } 5478 5479 synchronized (mCarrierRoamingNtnAllSatellitePlmnSetLock) { 5480 mCarrierRoamingNtnAllSatellitePlmnSet = allSatellitePlmnSet; 5481 } 5482 } 5483 } 5484 getCarrierRoamingNtnAllSatellitePlmnSetFromStorage()5485 private Set<String> getCarrierRoamingNtnAllSatellitePlmnSetFromStorage() { 5486 synchronized (mCarrierRoamingNtnAllSatellitePlmnSetLock) { 5487 if (mCarrierRoamingNtnAllSatellitePlmnSet != null) { 5488 plogd("getCarrierRoamingNtnAllSatellitePlmnSetFromStorage: " 5489 + mCarrierRoamingNtnAllSatellitePlmnSet); 5490 return mCarrierRoamingNtnAllSatellitePlmnSet; 5491 } 5492 } 5493 5494 if (!loadSatelliteSharedPreferences()) return new HashSet<>(); 5495 5496 if (mSharedPreferences == null) { 5497 ploge("getCarrierRoamingNtnAllSatellitePlmnSetFromStorage: mSharedPreferences is null"); 5498 return new HashSet<>(); 5499 } else { 5500 Set<String> allSatellitePlmnSet = new HashSet<>(); 5501 try { 5502 allSatellitePlmnSet = mSharedPreferences.getStringSet( 5503 CARRIER_ROAMING_NTN_ALL_SATELLITE_PLMN_SET_KEY, new HashSet<>()); 5504 } catch (Exception ex) { 5505 plogd("getCarrierRoamingNtnAllSatellitePlmnSetFromStorage: ex=" + ex); 5506 } 5507 5508 synchronized (mCarrierRoamingNtnAllSatellitePlmnSetLock) { 5509 mCarrierRoamingNtnAllSatellitePlmnSet = allSatellitePlmnSet; 5510 plogd("getCarrierRoamingNtnAllSatellitePlmnSetFromStorage: " 5511 + mCarrierRoamingNtnAllSatellitePlmnSet); 5512 return mCarrierRoamingNtnAllSatellitePlmnSet; 5513 } 5514 } 5515 } 5516 handleSetSatellitePlmnInfoDoneEvent(Message msg)5517 private void handleSetSatellitePlmnInfoDoneEvent(Message msg) { 5518 AsyncResult ar = (AsyncResult) msg.obj; 5519 SatelliteServiceUtils.getSatelliteError(ar, "handleSetSatellitePlmnInfoCmd"); 5520 } 5521 updateSupportedSatelliteServicesForActiveSubscriptions()5522 private void updateSupportedSatelliteServicesForActiveSubscriptions() { 5523 synchronized (mSupportedSatelliteServicesLock) { 5524 mSatelliteServicesSupportedByCarriersFromConfig.clear(); 5525 mMergedPlmnListPerCarrier.clear(); 5526 int[] activeSubIds = mSubscriptionManagerService.getActiveSubIdList(true); 5527 if (activeSubIds != null) { 5528 for (int subId : activeSubIds) { 5529 updateSupportedSatelliteServices(subId); 5530 handleCarrierRoamingNtnAvailableServicesChanged(subId); 5531 } 5532 } else { 5533 loge("updateSupportedSatelliteServicesForActiveSubscriptions: " 5534 + "activeSubIds is null"); 5535 } 5536 } 5537 } 5538 5539 /** 5540 * If the entitlementPlmnList exist then used it. 5541 * Otherwise, If the carrierPlmnList exist then used it. 5542 */ updatePlmnListPerCarrier(int subId)5543 private void updatePlmnListPerCarrier(int subId) { 5544 plogd("updatePlmnListPerCarrier: subId=" + subId); 5545 synchronized (mSupportedSatelliteServicesLock) { 5546 List<String> carrierPlmnList, entitlementPlmnList; 5547 if (getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, 5548 false)) { 5549 entitlementPlmnList = mEntitlementPlmnListPerCarrier.get(subId, 5550 new ArrayList<>()).stream().toList(); 5551 plogd("updatePlmnListPerCarrier: entitlementPlmnList=" 5552 + String.join(",", entitlementPlmnList) 5553 + " size=" + entitlementPlmnList.size()); 5554 if (!entitlementPlmnList.isEmpty()) { 5555 mMergedPlmnListPerCarrier.put(subId, entitlementPlmnList); 5556 plogd("mMergedPlmnListPerCarrier is updated by Entitlement"); 5557 mCarrierRoamingSatelliteControllerStats.reportConfigDataSource(subId, 5558 SatelliteConstants.CONFIG_DATA_SOURCE_ENTITLEMENT); 5559 return; 5560 } 5561 } 5562 5563 SatelliteConfig satelliteConfig = getSatelliteConfig(); 5564 if (satelliteConfig != null) { 5565 TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); 5566 int carrierId = tm.createForSubscriptionId(subId).getSimCarrierId(); 5567 List<String> plmnList = satelliteConfig.getAllSatellitePlmnsForCarrier(carrierId); 5568 if (!plmnList.isEmpty()) { 5569 plogd("mMergedPlmnListPerCarrier is updated by ConfigUpdater : " 5570 + String.join(",", plmnList)); 5571 mMergedPlmnListPerCarrier.put(subId, plmnList); 5572 mCarrierRoamingSatelliteControllerStats.reportConfigDataSource(subId, 5573 SatelliteConstants.CONFIG_DATA_SOURCE_CONFIG_UPDATER); 5574 return; 5575 } 5576 } 5577 5578 if (mSatelliteServicesSupportedByCarriersFromConfig.containsKey(subId) 5579 && mSatelliteServicesSupportedByCarriersFromConfig.get(subId) != null) { 5580 carrierPlmnList = 5581 mSatelliteServicesSupportedByCarriersFromConfig.get(subId).keySet() 5582 .stream().toList(); 5583 plogd("mMergedPlmnListPerCarrier is updated by carrier config: " 5584 + String.join(",", carrierPlmnList)); 5585 mCarrierRoamingSatelliteControllerStats.reportConfigDataSource(subId, 5586 SatelliteConstants.CONFIG_DATA_SOURCE_CARRIER_CONFIG); 5587 } else { 5588 carrierPlmnList = new ArrayList<>(); 5589 plogd("Empty mMergedPlmnListPerCarrier"); 5590 } 5591 mMergedPlmnListPerCarrier.put(subId, carrierPlmnList); 5592 } 5593 } 5594 updateSupportedSatelliteServices(int subId)5595 private void updateSupportedSatelliteServices(int subId) { 5596 plogd("updateSupportedSatelliteServices with subId " + subId); 5597 synchronized (mSupportedSatelliteServicesLock) { 5598 SatelliteConfig satelliteConfig = getSatelliteConfig(); 5599 5600 TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); 5601 int carrierId = tm.createForSubscriptionId(subId).getSimCarrierId(); 5602 5603 if (satelliteConfig != null) { 5604 Map<String, Set<Integer>> supportedServicesPerPlmn = 5605 satelliteConfig.getSupportedSatelliteServices(carrierId); 5606 if (!supportedServicesPerPlmn.isEmpty()) { 5607 mSatelliteServicesSupportedByCarriersFromConfig.put(subId, 5608 supportedServicesPerPlmn); 5609 plogd("updateSupportedSatelliteServices using ConfigUpdater, " 5610 + "supportedServicesPerPlmn = " + supportedServicesPerPlmn.size()); 5611 updatePlmnListPerCarrier(subId); 5612 return; 5613 } else { 5614 plogd("supportedServicesPerPlmn is empty"); 5615 } 5616 } 5617 5618 mSatelliteServicesSupportedByCarriersFromConfig.put( 5619 subId, readSupportedSatelliteServicesFromCarrierConfig(subId)); 5620 updatePlmnListPerCarrier(subId); 5621 plogd("updateSupportedSatelliteServices using carrier config"); 5622 } 5623 } 5624 5625 @NonNull readSatellitePlmnsFromOverlayConfig()5626 private List<String> readSatellitePlmnsFromOverlayConfig() { 5627 String[] devicePlmns = readStringArrayFromOverlayConfig( 5628 R.array.config_satellite_providers); 5629 return Arrays.stream(devicePlmns).toList(); 5630 } 5631 5632 @NonNull readSupportedSatelliteServicesFromCarrierConfig(int subId)5633 private Map<String, Set<Integer>> readSupportedSatelliteServicesFromCarrierConfig(int subId) { 5634 PersistableBundle config = getPersistableBundle(subId); 5635 return SatelliteServiceUtils.parseSupportedSatelliteServices( 5636 config.getPersistableBundle( 5637 KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE)); 5638 } 5639 5640 @NonNull readRegionalSatelliteEarfcnsFromCarrierConfig(int subId)5641 private Map<String, Set<Integer>> readRegionalSatelliteEarfcnsFromCarrierConfig(int subId) { 5642 PersistableBundle config = getPersistableBundle(subId); 5643 return SatelliteServiceUtils.parseRegionalSatelliteEarfcns( 5644 config.getPersistableBundle(KEY_REGIONAL_SATELLITE_EARFCN_BUNDLE)); 5645 } 5646 getConfigForSubId(int subId)5647 @NonNull private PersistableBundle getConfigForSubId(int subId) { 5648 PersistableBundle config = null; 5649 if (mCarrierConfigManager != null) { 5650 try { 5651 config = mCarrierConfigManager.getConfigForSubId(subId, 5652 KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE, 5653 KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, 5654 KEY_SATELLITE_DISPLAY_NAME_STRING, 5655 KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL, 5656 KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT, 5657 KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, 5658 KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY, 5659 KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL, 5660 KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT, 5661 KEY_SATELLITE_ESOS_SUPPORTED_BOOL, 5662 KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL, 5663 KEY_SATELLITE_NIDD_APN_NAME_STRING, 5664 KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 5665 KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT, 5666 KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT, 5667 KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT, 5668 KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT, 5669 KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT, 5670 KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE_BYTES_INT, 5671 KEY_SATELLITE_SUPPORTED_MSG_APPS_STRING_ARRAY, 5672 KEY_REGIONAL_SATELLITE_EARFCN_BUNDLE, 5673 KEY_SATELLITE_DATA_SUPPORT_MODE_INT, 5674 KEY_SATELLITE_CONNECTED_NOTIFICATION_THROTTLE_MILLIS_INT 5675 ); 5676 } catch (Exception e) { 5677 logw("getConfigForSubId: " + e); 5678 } 5679 } 5680 if (config == null || config.isEmpty()) { 5681 config = CarrierConfigManager.getDefaultConfig(); 5682 } 5683 return config; 5684 } 5685 handleCarrierConfigChanged(int slotIndex, int subId, int carrierId, int specificCarrierId)5686 private void handleCarrierConfigChanged(int slotIndex, int subId, int carrierId, 5687 int specificCarrierId) { 5688 plogd("handleCarrierConfigChanged(): slotIndex(" + slotIndex + "), subId(" 5689 + subId + "), carrierId(" + carrierId + "), specificCarrierId(" 5690 + specificCarrierId + ")"); 5691 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 5692 return; 5693 } 5694 5695 getSatelliteEnabledForCarrierAtModem(subId); 5696 updateCarrierConfig(subId); 5697 updateSatelliteESOSSupported(subId); 5698 updateSatelliteProvisionedStatePerSubscriberId(); 5699 updateEntitlementPlmnListPerCarrier(subId); 5700 updateSupportedSatelliteServicesForActiveSubscriptions(); 5701 processNewCarrierConfigData(subId); 5702 resetCarrierRoamingSatelliteModeParams(subId); 5703 evaluateCarrierRoamingNtnEligibilityChange(); 5704 sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION), 5705 mEvaluateEsosProfilesPrioritizationDurationMillis); 5706 updateRegionalSatelliteEarfcns(subId); 5707 } 5708 getSatelliteEnabledForCarrierAtModem(int subId)5709 private void getSatelliteEnabledForCarrierAtModem(int subId) { 5710 Phone phone = SatelliteServiceUtils.getPhone(subId); 5711 synchronized (mIsSatelliteEnabledLock) { 5712 if (!mIsSatelliteAttachEnabledForCarrierArrayPerSub.containsKey(subId)) { 5713 // Get enabled status from modem for new subscription 5714 sendRequestAsync(CMD_GET_SATELLITE_ENABLED_FOR_CARRIER, null, phone); 5715 } 5716 } 5717 } 5718 5719 // imsi, msisdn, default sms subId change handleSubscriptionsChanged()5720 private void handleSubscriptionsChanged() { 5721 sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION), 5722 mEvaluateEsosProfilesPrioritizationDurationMillis); 5723 } 5724 processNewCarrierConfigData(int subId)5725 private void processNewCarrierConfigData(int subId) { 5726 updateRestrictReasonForEntitlementPerCarrier(subId); 5727 configureSatellitePlmnForCarrier(subId); 5728 evaluateEnablingSatelliteForCarrier(subId, 5729 SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, null); 5730 } 5731 5732 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) updateCarrierConfig(int subId)5733 protected void updateCarrierConfig(int subId) { 5734 synchronized (mCarrierConfigArrayLock) { 5735 mCarrierConfigArray.put(subId, getConfigForSubId(subId)); 5736 } 5737 } 5738 5739 /** 5740 * If there is no cached entitlement plmn list, read it from the db and use it if it is not an 5741 * empty list. 5742 */ updateEntitlementPlmnListPerCarrier(int subId)5743 private void updateEntitlementPlmnListPerCarrier(int subId) { 5744 if (!getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false)) { 5745 plogd("don't support entitlement"); 5746 return; 5747 } 5748 5749 synchronized (mSupportedSatelliteServicesLock) { 5750 if (mEntitlementPlmnListPerCarrier.indexOfKey(subId) < 0) { 5751 plogd("updateEntitlementPlmnListPerCarrier: no correspondent cache, load from " 5752 + "persist storage"); 5753 List<String> entitlementPlmnList = 5754 mSubscriptionManagerService.getSatelliteEntitlementPlmnList(subId); 5755 if (entitlementPlmnList.isEmpty()) { 5756 plogd("updateEntitlementPlmnListPerCarrier: read empty list"); 5757 return; 5758 } 5759 plogd("updateEntitlementPlmnListPerCarrier: entitlementPlmnList=" + String.join(",", 5760 entitlementPlmnList)); 5761 mEntitlementPlmnListPerCarrier.put(subId, entitlementPlmnList); 5762 } 5763 5764 if (mEntitlementBarredPlmnListPerCarrier.indexOfKey(subId) < 0) { 5765 plogd("updateEntitlementBarredPlmnList: no correspondent cache, load from " 5766 + "persist storage"); 5767 List<String> entitlementBarredPlmnList = 5768 mSubscriptionManagerService.getSatelliteEntitlementBarredPlmnList(subId); 5769 if (entitlementBarredPlmnList.isEmpty()) { 5770 plogd("updateEntitlementBarredPlmnList: read empty list"); 5771 return; 5772 } 5773 plogd("updateEntitlementBarredPlmnList: entitlementBarredPlmnList=" + String.join( 5774 ",", entitlementBarredPlmnList)); 5775 mEntitlementBarredPlmnListPerCarrier.put(subId, entitlementBarredPlmnList); 5776 } 5777 5778 if (mEntitlementDataPlanMapPerCarrier.indexOfKey(subId) < 0) { 5779 plogd("updateEntitlementDataPlanForPlmns: no correspondent cache, load from " 5780 + "persist storage"); 5781 Map<String, Integer> entitlementDataPlanForPlmns = 5782 mSubscriptionManagerService.getSatelliteEntitlementDataPlanForPlmns(subId); 5783 if (entitlementDataPlanForPlmns.isEmpty()) { 5784 plogd("updateEntitlementBarredPlmnList: read empty list"); 5785 return; 5786 } 5787 plogd("updateEntitlementDataPlanForPlmns: entitlementDataPlanForPlmns=" 5788 + entitlementDataPlanForPlmns); 5789 mEntitlementDataPlanMapPerCarrier.put(subId, entitlementDataPlanForPlmns); 5790 } 5791 5792 if (mEntitlementServiceTypeMapPerCarrier.indexOfKey(subId) < 0) { 5793 plogd("updateEntitlementTypeMapPerCarrier: no correspondent cache, load from " 5794 + "persist storage"); 5795 Map<String, List<Integer>> entitlementTypeMapPerCarrier = 5796 mSubscriptionManagerService.getSatelliteEntitlementPlmnServiceTypeMap( 5797 subId); 5798 if (entitlementTypeMapPerCarrier.isEmpty()) { 5799 plogd("updateEntitlementTypeMapPerCarrier: read empty list"); 5800 return; 5801 } 5802 plogd("updateEntitlementTypeMapPerCarrier: entitlementTypeMapPerCarrier=" 5803 + entitlementTypeMapPerCarrier); 5804 mEntitlementServiceTypeMapPerCarrier.put(subId, entitlementTypeMapPerCarrier); 5805 } 5806 5807 if (mEntitlementDataServicePolicyMapPerCarrier.indexOfKey(subId) < 0) { 5808 plogd("updateEntitlementDataServicePolicy: no correspondent cache, load from " 5809 + "persist storage"); 5810 Map<String, Integer> entitlementDataServicePolicy = 5811 mSubscriptionManagerService.getSatelliteEntitlementPlmnDataServicePolicy( 5812 subId); 5813 if (entitlementDataServicePolicy.isEmpty()) { 5814 plogd("updateEntitlementDataServicePolicy: read empty list"); 5815 return; 5816 } 5817 plogd("updateEntitlementDataServicePolicy: entitlementDataServicePolicy=" 5818 + entitlementDataServicePolicy); 5819 mEntitlementDataServicePolicyMapPerCarrier.put(subId, entitlementDataServicePolicy); 5820 } 5821 5822 if (mEntitlementVoiceServicePolicyMapPerCarrier.indexOfKey(subId) < 0) { 5823 plogd("updateEntitlementVoiceServicePolicy: no correspondent cache, load from " 5824 + "persist storage"); 5825 Map<String, Integer> entitlementVoiceServicePolicy = 5826 mSubscriptionManagerService.getSatelliteEntitlementPlmnVoiceServicePolicy( 5827 subId); 5828 if (entitlementVoiceServicePolicy.isEmpty()) { 5829 plogd("updateEntitlementVoiceServicePolicy: read empty list"); 5830 return; 5831 } 5832 plogd("updateEntitlementVoiceServicePolicy: entitlementVoiceServicePolicy=" 5833 + entitlementVoiceServicePolicy); 5834 mEntitlementVoiceServicePolicyMapPerCarrier.put(subId, 5835 entitlementVoiceServicePolicy); 5836 } 5837 } 5838 } 5839 5840 /** 5841 * Update the value of SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED stored in the database based 5842 * on the value in the carrier config. 5843 */ updateSatelliteESOSSupported(int subId)5844 private void updateSatelliteESOSSupported(int subId) { 5845 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 5846 return; 5847 } 5848 5849 boolean isSatelliteESosSupportedFromDB = 5850 mSubscriptionManagerService.getSatelliteESOSSupported(subId); 5851 boolean isSatelliteESosSupportedFromCarrierConfig = getConfigForSubId(subId).getBoolean( 5852 KEY_SATELLITE_ESOS_SUPPORTED_BOOL, false); 5853 if (isSatelliteESosSupportedFromDB != isSatelliteESosSupportedFromCarrierConfig) { 5854 mSubscriptionManagerService.setSatelliteESOSSupported(subId, 5855 isSatelliteESosSupportedFromCarrierConfig); 5856 logd("updateSatelliteESOSSupported: " + isSatelliteESosSupportedFromCarrierConfig); 5857 } 5858 } 5859 5860 /** If the provision state per subscriberId for the cached is not exist, check the database for 5861 * the corresponding value and use it. */ updateSatelliteProvisionedStatePerSubscriberId()5862 protected void updateSatelliteProvisionedStatePerSubscriberId() { 5863 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 5864 return; 5865 } 5866 5867 List<SubscriptionInfo> allSubInfos = mSubscriptionManagerService.getAllSubInfoList( 5868 mContext.getOpPackageName(), mContext.getAttributionTag()); 5869 for (SubscriptionInfo info : allSubInfos) { 5870 int subId = info.getSubscriptionId(); 5871 Pair<String, Integer> subscriberIdPair = getSubscriberIdAndType( 5872 mSubscriptionManagerService.getSubscriptionInfo(subId)); 5873 String subscriberId = subscriberIdPair.first; 5874 synchronized (mSatelliteTokenProvisionedLock) { 5875 if (mProvisionedSubscriberId.get(subscriberId) == null) { 5876 boolean Provisioned = mSubscriptionManagerService 5877 .isSatelliteProvisionedForNonIpDatagram(subId); 5878 if (Provisioned) { 5879 mProvisionedSubscriberId.put(subscriberId, true); 5880 logd("updateSatelliteProvisionStatePerSubscriberId: " 5881 + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, subscriberId) 5882 + " set true"); 5883 } 5884 } 5885 } 5886 } 5887 // Need to update the provision status of the device 5888 updateCachedDeviceProvisionStatus(); 5889 } 5890 5891 @NonNull readStringArrayFromOverlayConfig(@rrayRes int id)5892 private String[] readStringArrayFromOverlayConfig(@ArrayRes int id) { 5893 String[] strArray = null; 5894 try { 5895 strArray = mContext.getResources().getStringArray(id); 5896 } catch (Resources.NotFoundException ex) { 5897 ploge("readStringArrayFromOverlayConfig: id= " + id + ", ex=" + ex); 5898 } 5899 if (strArray == null) { 5900 strArray = new String[0]; 5901 } 5902 return strArray; 5903 } 5904 isSatelliteSupportedViaCarrier(int subId)5905 private boolean isSatelliteSupportedViaCarrier(int subId) { 5906 return getConfigForSubId(subId) 5907 .getBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL); 5908 } 5909 5910 /** 5911 * Return whether the device support P2P SMS mode from carrier config. 5912 * 5913 * @param subId Associated subscription ID 5914 */ 5915 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) isSatelliteRoamingP2pSmSSupported(int subId)5916 public boolean isSatelliteRoamingP2pSmSSupported(int subId) { 5917 return getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL); 5918 } 5919 5920 /** 5921 * Return whether the device support ESOS mode from carrier config. 5922 * 5923 * @param subId Associated subscription ID 5924 */ 5925 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) isSatelliteEsosSupported(int subId)5926 public boolean isSatelliteEsosSupported(int subId) { 5927 return getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL); 5928 } 5929 5930 /** 5931 * Return whether the device allows to turn off satellite session for emergency call. 5932 * 5933 * @param subId Associated subscription ID 5934 */ 5935 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) turnOffSatelliteSessionForEmergencyCall(int subId)5936 public boolean turnOffSatelliteSessionForEmergencyCall(int subId) { 5937 return getConfigForSubId(subId).getBoolean( 5938 KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL); 5939 } 5940 getCarrierRoamingNtnConnectType(int subId)5941 private int getCarrierRoamingNtnConnectType(int subId) { 5942 return getConfigForSubId(subId).getInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT); 5943 } 5944 getCarrierRoamingNtnEmergencyCallToSatelliteHandoverType(int subId)5945 protected int getCarrierRoamingNtnEmergencyCallToSatelliteHandoverType(int subId) { 5946 return getConfigForSubId(subId).getInt( 5947 KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT); 5948 } 5949 5950 @CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE getCarrierSatelliteDataSupportedModeFromConfig(int subId)5951 private int getCarrierSatelliteDataSupportedModeFromConfig(int subId) { 5952 return getConfigForSubId(subId).getInt(KEY_SATELLITE_DATA_SUPPORT_MODE_INT); 5953 } 5954 5955 /** 5956 * Satellite notification display restriction timeout. Default value is 7 days in millis. 5957 * @param subId : subscription Id. 5958 * @return : Notification throttle timeout in millis. 5959 */ getNotificationDisplayThrottleTimeout(int subId)5960 private long getNotificationDisplayThrottleTimeout(int subId) { 5961 if (Flags.starlinkDataBugfix()) { 5962 return getConfigForSubId(subId).getLong( 5963 KEY_SATELLITE_CONNECTED_NOTIFICATION_THROTTLE_MILLIS_INT); 5964 } else { 5965 return TimeUnit.DAYS.toMillis(7); 5966 } 5967 } 5968 5969 /** 5970 * Check if satellite attach is enabled by user for the carrier associated with the 5971 * {@code subId}. 5972 * 5973 * @param subId Subscription ID. 5974 * 5975 * @return Returns {@code true} if satellite attach for carrier is enabled by user, 5976 * {@code false} otherwise. 5977 */ isSatelliteAttachEnabledForCarrierByUser(int subId)5978 private boolean isSatelliteAttachEnabledForCarrierByUser(int subId) { 5979 synchronized (mIsSatelliteEnabledLock) { 5980 Set<Integer> cachedRestrictionSet = 5981 mSatelliteAttachRestrictionForCarrierArray.get(subId); 5982 if (cachedRestrictionSet != null) { 5983 return !cachedRestrictionSet.contains( 5984 SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER); 5985 } else { 5986 plogd("isSatelliteAttachEnabledForCarrierByUser() no correspondent cache, " 5987 + "load from persist storage"); 5988 try { 5989 String enabled = 5990 mSubscriptionManagerService.getSubscriptionProperty(subId, 5991 SATELLITE_ATTACH_ENABLED_FOR_CARRIER, 5992 mContext.getOpPackageName(), mContext.getAttributionTag()); 5993 5994 if (enabled == null) { 5995 ploge("isSatelliteAttachEnabledForCarrierByUser: invalid subId, subId=" 5996 + subId); 5997 return false; 5998 } 5999 6000 if (enabled.isEmpty()) { 6001 ploge("isSatelliteAttachEnabledForCarrierByUser: no data for subId(" + subId 6002 + ")"); 6003 return false; 6004 } 6005 6006 synchronized (mIsSatelliteEnabledLock) { 6007 boolean result = enabled.equals("1"); 6008 if (!result) { 6009 mSatelliteAttachRestrictionForCarrierArray.put(subId, new HashSet<>()); 6010 mSatelliteAttachRestrictionForCarrierArray.get(subId).add( 6011 SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER); 6012 } 6013 return result; 6014 } 6015 } catch (IllegalArgumentException | SecurityException ex) { 6016 ploge("isSatelliteAttachEnabledForCarrierByUser: ex=" + ex); 6017 return false; 6018 } 6019 } 6020 } 6021 } 6022 6023 /** 6024 * Check whether there is any reason to restrict satellite communication for the carrier 6025 * associated with the {@code subId}. 6026 * 6027 * @param subId Subscription ID 6028 * @return {@code true} when there is at least on reason, {@code false} otherwise. 6029 */ hasReasonToRestrictSatelliteCommunicationForCarrier(int subId)6030 private boolean hasReasonToRestrictSatelliteCommunicationForCarrier(int subId) { 6031 synchronized (mIsSatelliteEnabledLock) { 6032 return !mSatelliteAttachRestrictionForCarrierArray 6033 .getOrDefault(subId, Collections.emptySet()).isEmpty(); 6034 } 6035 } 6036 updateRestrictReasonForEntitlementPerCarrier(int subId)6037 private void updateRestrictReasonForEntitlementPerCarrier(int subId) { 6038 if (!getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false)) { 6039 plogd("don't support entitlement"); 6040 return; 6041 } 6042 6043 IIntegerConsumer callback = new IIntegerConsumer.Stub() { 6044 @Override 6045 public void accept(int result) { 6046 plogd("updateRestrictReasonForEntitlementPerCarrier:" + result); 6047 } 6048 }; 6049 synchronized (mSupportedSatelliteServicesLock) { 6050 if (mSatelliteEntitlementStatusPerCarrier.indexOfKey(subId) < 0) { 6051 plogd("updateRestrictReasonForEntitlementPerCarrier: no correspondent cache, " 6052 + "load from persist storage"); 6053 String entitlementStatus = null; 6054 try { 6055 entitlementStatus = 6056 mSubscriptionManagerService.getSubscriptionProperty(subId, 6057 SATELLITE_ENTITLEMENT_STATUS, mContext.getOpPackageName(), 6058 mContext.getAttributionTag()); 6059 } catch (IllegalArgumentException | SecurityException e) { 6060 ploge("updateRestrictReasonForEntitlementPerCarrier, e=" + e); 6061 } 6062 6063 if (entitlementStatus == null) { 6064 ploge("updateRestrictReasonForEntitlementPerCarrier: invalid subId, subId=" 6065 + subId + " set to default value"); 6066 entitlementStatus = "0"; 6067 } 6068 6069 if (entitlementStatus.isEmpty()) { 6070 ploge("updateRestrictReasonForEntitlementPerCarrier: no data for subId(" + subId 6071 + "). set to default value"); 6072 entitlementStatus = "0"; 6073 } 6074 boolean result = entitlementStatus.equals("1"); 6075 mSatelliteEntitlementStatusPerCarrier.put(subId, result); 6076 mCarrierRoamingSatelliteControllerStats.reportIsDeviceEntitled(subId, result); 6077 if (hasMessages(EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT)) { 6078 removeMessages(EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT); 6079 sendMessageDelayed(obtainMessage( 6080 EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT), 6081 WAIT_FOR_REPORT_ENTITLED_MERTICS_TIMEOUT_MILLIS); 6082 } 6083 } 6084 6085 if (!mSatelliteEntitlementStatusPerCarrier.get(subId, false)) { 6086 addAttachRestrictionForCarrier(subId, 6087 SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT, callback); 6088 } 6089 } 6090 } 6091 6092 /** 6093 * Save user setting for enabling satellite attach for the carrier associated with the 6094 * {@code subId} to persistent storage. 6095 * 6096 * @param subId Subscription ID. 6097 * 6098 * @return {@code true} if persist successful, {@code false} otherwise. 6099 */ 6100 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) persistSatelliteAttachEnabledForCarrierSetting(int subId)6101 protected boolean persistSatelliteAttachEnabledForCarrierSetting(int subId) { 6102 plogd("persistSatelliteAttachEnabledForCarrierSetting"); 6103 if (!isValidSubscriptionId(subId)) { 6104 ploge("persistSatelliteAttachEnabledForCarrierSetting: subId is not valid," 6105 + " subId=" + subId); 6106 return false; 6107 } 6108 6109 synchronized (mIsSatelliteEnabledLock) { 6110 try { 6111 mSubscriptionManagerService.setSubscriptionProperty(subId, 6112 SATELLITE_ATTACH_ENABLED_FOR_CARRIER, 6113 mSatelliteAttachRestrictionForCarrierArray.get(subId) 6114 .contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER) 6115 ? "0" : "1"); 6116 } catch (IllegalArgumentException | SecurityException ex) { 6117 ploge("persistSatelliteAttachEnabledForCarrierSetting, ex=" + ex); 6118 return false; 6119 } 6120 } 6121 return true; 6122 } 6123 6124 /** 6125 * Evaluate whether satellite attach for carrier should be restricted. 6126 * 6127 * @param subId Subscription Id to evaluate for. 6128 * @return {@code true} satellite attach is restricted, {@code false} otherwise. 6129 */ isSatelliteRestrictedForCarrier(int subId)6130 private boolean isSatelliteRestrictedForCarrier(int subId) { 6131 return !isSatelliteAttachEnabledForCarrierByUser(subId) 6132 || hasReasonToRestrictSatelliteCommunicationForCarrier(subId); 6133 } 6134 6135 /** 6136 * Check whether satellite is enabled for carrier at modem. 6137 * 6138 * @param subId subscription ID 6139 * @return {@code true} if satellite modem is enabled, {@code false} otherwise. 6140 */ 6141 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) isSatelliteEnabledForCarrierAtModem(int subId)6142 public boolean isSatelliteEnabledForCarrierAtModem(int subId) { 6143 synchronized (mIsSatelliteEnabledLock) { 6144 return mIsSatelliteAttachEnabledForCarrierArrayPerSub.getOrDefault(subId, false); 6145 } 6146 } 6147 6148 /** 6149 * Evaluate whether satellite modem for carrier should be enabled or not. 6150 * <p> 6151 * Satellite will be enabled only when the following conditions are met: 6152 * <ul> 6153 * <li>Users want to enable it.</li> 6154 * <li>There is no satellite communication restriction, which is added by 6155 * {@link #addAttachRestrictionForCarrier(int, int, IIntegerConsumer)}</li> 6156 * <li>The carrier config {@link 6157 * android.telephony.CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} is set to 6158 * {@code true}.</li> 6159 * </ul> 6160 * 6161 * @param subId Subscription Id for evaluate for. 6162 * @param callback The callback for getting the result of enabling satellite. 6163 */ evaluateEnablingSatelliteForCarrier(int subId, int reason, @Nullable Consumer<Integer> callback)6164 private void evaluateEnablingSatelliteForCarrier(int subId, int reason, 6165 @Nullable Consumer<Integer> callback) { 6166 if (callback == null) { 6167 callback = errorCode -> plogd("evaluateEnablingSatelliteForCarrier: " 6168 + "SetSatelliteAttachEnableForCarrier error code =" + errorCode); 6169 } 6170 6171 Phone phone = SatelliteServiceUtils.getPhone(subId); 6172 if (phone == null) { 6173 ploge("evaluateEnablingSatelliteForCarrier: phone is null for subId=" + subId); 6174 callback.accept(SATELLITE_RESULT_INVALID_TELEPHONY_STATE); 6175 return; 6176 } 6177 6178 /* Request to enable or disable the satellite in the cellular modem only when the desired 6179 state and the current state are different. */ 6180 boolean isSatelliteExpectedToBeEnabled = !isSatelliteRestrictedForCarrier(subId) 6181 && isSatelliteSupportedViaCarrier(subId); 6182 boolean isSatelliteEnabledForCarrierAtModem = isSatelliteEnabledForCarrierAtModem( 6183 phone.getSubId()); 6184 plogd("evaluateEnablingSatelliteForCarrier: subId=" + subId + " reason=" + reason 6185 + " isSatelliteExpectedToBeEnabled=" + isSatelliteExpectedToBeEnabled 6186 + " isSatelliteEnabledForCarrierAtModem=" + isSatelliteEnabledForCarrierAtModem); 6187 6188 if (isSatelliteExpectedToBeEnabled != isSatelliteEnabledForCarrierAtModem) { 6189 int simSlot = SubscriptionManager.getSlotIndex(subId); 6190 RequestHandleSatelliteAttachRestrictionForCarrierArgument argument = 6191 new RequestHandleSatelliteAttachRestrictionForCarrierArgument(subId, 6192 reason, callback); 6193 SatelliteControllerHandlerRequest request = 6194 new SatelliteControllerHandlerRequest(argument, 6195 SatelliteServiceUtils.getPhone(subId)); 6196 Message onCompleted = obtainMessage( 6197 EVENT_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE_DONE, request); 6198 phone.setSatelliteEnabledForCarrier(simSlot, 6199 isSatelliteExpectedToBeEnabled, onCompleted); 6200 } else { 6201 callback.accept(SATELLITE_RESULT_SUCCESS); 6202 } 6203 } 6204 evaluateOemSatelliteRequestAllowed( boolean isProvisionRequired)6205 @SatelliteManager.SatelliteResult private int evaluateOemSatelliteRequestAllowed( 6206 boolean isProvisionRequired) { 6207 if (!mSatelliteModemInterface.isSatelliteServiceSupported()) { 6208 plogd("evaluateOemSatelliteRequestAllowed: satellite service is not supported"); 6209 return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED; 6210 } 6211 6212 Boolean satelliteSupported = isSatelliteSupportedViaOemInternal(); 6213 if (satelliteSupported == null) { 6214 plogd("evaluateOemSatelliteRequestAllowed: satelliteSupported is null"); 6215 return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 6216 } 6217 if (!satelliteSupported) { 6218 return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED; 6219 } 6220 6221 if (isProvisionRequired) { 6222 Boolean satelliteProvisioned = isDeviceProvisioned(); 6223 if (satelliteProvisioned == null) { 6224 plogd("evaluateOemSatelliteRequestAllowed: satelliteProvisioned is null"); 6225 return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE; 6226 } 6227 if (!satelliteProvisioned) { 6228 plogd("evaluateOemSatelliteRequestAllowed: satellite service is not provisioned"); 6229 return SatelliteManager.SATELLITE_RESULT_SERVICE_NOT_PROVISIONED; 6230 } 6231 } 6232 6233 return SATELLITE_RESULT_SUCCESS; 6234 } 6235 6236 /** 6237 * Returns the non-terrestrial network radio technology that the satellite modem currently 6238 * supports. If multiple technologies are available, returns the first supported technology. 6239 */ 6240 @VisibleForTesting getSupportedNtnRadioTechnology()6241 protected @SatelliteManager.NTRadioTechnology int getSupportedNtnRadioTechnology() { 6242 SatelliteCapabilities satelliteCapabilities = getSatelliteCapabilities(); 6243 if (satelliteCapabilities != null) { 6244 return satelliteCapabilities.getSupportedRadioTechnologies() 6245 .stream().findFirst().orElse(SatelliteManager.NT_RADIO_TECHNOLOGY_UNKNOWN); 6246 } 6247 return SatelliteManager.NT_RADIO_TECHNOLOGY_UNKNOWN; 6248 } 6249 6250 /** 6251 * Returns a list of messaging apps that support satellite. 6252 */ getSatelliteSupportedMsgApps(int subId)6253 @NonNull public List<String> getSatelliteSupportedMsgApps(int subId) { 6254 String[] satelliteSupportedMsgApps = getConfigForSubId(subId) 6255 .getStringArray(KEY_SATELLITE_SUPPORTED_MSG_APPS_STRING_ARRAY); 6256 6257 return satelliteSupportedMsgApps != null 6258 ? List.of(satelliteSupportedMsgApps) : Collections.emptyList(); 6259 } 6260 sendErrorAndReportSessionMetrics(@atelliteManager.SatelliteResult int error, Consumer<Integer> result)6261 private void sendErrorAndReportSessionMetrics(@SatelliteManager.SatelliteResult int error, 6262 Consumer<Integer> result) { 6263 result.accept(error); 6264 mSessionMetricsStats.setInitializationResult(error) 6265 .setSatelliteTechnology(getSupportedNtnRadioTechnology()) 6266 .setIsDemoMode(mIsDemoModeEnabled) 6267 .setCarrierId(getSatelliteCarrierId()) 6268 .setIsNtnOnlyCarrier(isNtnOnlyCarrier()) 6269 .reportSessionMetrics(); 6270 mSessionStartTimeStamp = 0; 6271 mSessionProcessingTimeStamp = 0; 6272 } 6273 isNtnOnlyCarrier()6274 public boolean isNtnOnlyCarrier() { 6275 synchronized (mSatelliteTokenProvisionedLock) { 6276 if (mSelectedSatelliteSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 6277 return false; 6278 } 6279 return mSelectedSatelliteSubId == getNtnOnlySubscriptionId(); 6280 } 6281 } 6282 registerForServiceStateChanged()6283 private void registerForServiceStateChanged() { 6284 for (Phone phone : PhoneFactory.getPhones()) { 6285 phone.registerForServiceStateChanged(this, EVENT_SERVICE_STATE_CHANGED, null); 6286 } 6287 } 6288 registerForSignalStrengthChanged()6289 private void registerForSignalStrengthChanged() { 6290 for (Phone phone : PhoneFactory.getPhones()) { 6291 phone.getSignalStrengthController().registerForSignalStrengthChanged(this, 6292 EVENT_SIGNAL_STRENGTH_CHANGED, phone.getPhoneId()); 6293 } 6294 } 6295 handleEventServiceStateChanged()6296 private void handleEventServiceStateChanged() { 6297 evaluateCarrierRoamingNtnEligibilityChange(); 6298 handleServiceStateForSatelliteConnectionViaCarrier(); 6299 } 6300 handleServiceStateForSatelliteConnectionViaCarrier()6301 private void handleServiceStateForSatelliteConnectionViaCarrier() { 6302 for (Phone phone : PhoneFactory.getPhones()) { 6303 int subId = phone.getSubId(); 6304 ServiceState serviceState = phone.getServiceState(); 6305 if (serviceState == null || subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 6306 continue; 6307 } 6308 6309 synchronized (mSatelliteConnectedLock) { 6310 CarrierRoamingSatelliteSessionStats sessionStats = 6311 mCarrierRoamingSatelliteSessionStatsMap.get(subId); 6312 if (DEBUG) { 6313 plogd("handleServiceStateForSatelliteConnectionViaCarrier : SubId = " + subId 6314 + " isUsingNonTerrestrialNetwork = " 6315 + serviceState.isUsingNonTerrestrialNetwork()); 6316 } 6317 if (serviceState.isUsingNonTerrestrialNetwork()) { 6318 if (sessionStats != null) { 6319 sessionStats.onSignalStrength(phone); 6320 if (!mWasSatelliteConnectedViaCarrier.get(subId)) { 6321 // Log satellite connection start 6322 sessionStats.onConnectionStart(phone); 6323 } 6324 } 6325 6326 resetCarrierRoamingSatelliteModeParams(subId); 6327 mWasSatelliteConnectedViaCarrier.put(subId, true); 6328 6329 for (NetworkRegistrationInfo nri 6330 : serviceState.getNetworkRegistrationInfoList()) { 6331 if (nri.isNonTerrestrialNetwork()) { 6332 mSatModeCapabilitiesForCarrierRoaming.put(subId, 6333 nri.getAvailableServices()); 6334 } 6335 } 6336 } else { 6337 Boolean connected = mWasSatelliteConnectedViaCarrier.get(subId); 6338 if (getWwanIsInService(serviceState) 6339 || serviceState.getState() == ServiceState.STATE_POWER_OFF) { 6340 resetCarrierRoamingSatelliteModeParams(subId); 6341 } else if (connected != null && connected) { 6342 // The device just got disconnected from a satellite network 6343 // and is not connected to any terrestrial network that has coverage 6344 mLastSatelliteDisconnectedTimesMillis.put(subId, getElapsedRealtime()); 6345 6346 plogd("sendMessageDelayed subId:" + subId 6347 + " phoneId:" + phone.getPhoneId() 6348 + " time:" + getSatelliteConnectionHysteresisTimeMillis(subId)); 6349 sendMessageDelayed(obtainMessage(EVENT_NOTIFY_NTN_HYSTERESIS_TIMED_OUT, 6350 phone.getPhoneId()), 6351 getSatelliteConnectionHysteresisTimeMillis(subId)); 6352 6353 if (sessionStats != null) { 6354 // Log satellite connection end 6355 sessionStats.onConnectionEnd(); 6356 } 6357 } 6358 mWasSatelliteConnectedViaCarrier.put(subId, false); 6359 } 6360 updateLastNotifiedNtnModeAndNotify(phone); 6361 updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(phone); 6362 } 6363 } 6364 determineAutoConnectSystemNotification(); 6365 } 6366 updateLastNotifiedNtnModeAndNotify(@ullable Phone phone)6367 private void updateLastNotifiedNtnModeAndNotify(@Nullable Phone phone) { 6368 if (phone == null) { 6369 plogd("updateLastNotifiedNtnModeAndNotify: phone is null"); 6370 return; 6371 } 6372 6373 int subId = phone.getSubId(); 6374 synchronized (mSatelliteConnectedLock) { 6375 boolean initialized = mInitialized.get(subId); 6376 boolean lastNotifiedNtnMode = mLastNotifiedNtnMode.get(subId); 6377 boolean currNtnMode = isInSatelliteModeForCarrierRoaming(phone); 6378 plogd("updateLastNotifiedNtnModeAndNotify: subId=" + subId 6379 + " initialized=" + initialized 6380 + " lastNotifiedNtnMode=" + lastNotifiedNtnMode 6381 + " currNtnMode=" + currNtnMode); 6382 if (!initialized || lastNotifiedNtnMode != currNtnMode) { 6383 if (!initialized) mInitialized.put(subId, true); 6384 mLastNotifiedNtnMode.put(subId, currNtnMode); 6385 phone.notifyCarrierRoamingNtnModeChanged(currNtnMode); 6386 updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(phone); 6387 logCarrierRoamingSatelliteSessionStats(phone, lastNotifiedNtnMode, currNtnMode); 6388 if(mIsNotificationShowing && !currNtnMode) { 6389 dismissSatelliteNotification(); 6390 } 6391 } 6392 } 6393 } 6394 6395 /** 6396 * map data policy to support unknown case at metrics 6397 * @param dataPolicy data support mode for the service type 6398 * @return corresponding value from {@link SatelliteConstants.SatelliteEntitlementServicePolicy} 6399 * 6400 */ 6401 @SatelliteConstants.SatelliteEntitlementServicePolicy mapDataPolicyForMetrics(int dataPolicy)6402 public int mapDataPolicyForMetrics(int dataPolicy) { 6403 switch (dataPolicy) { 6404 case CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED -> { 6405 return SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_RESTRICTED; 6406 } 6407 case CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED -> { 6408 return SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_CONSTRAINED; 6409 } 6410 case CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL -> { 6411 return SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNCONSTRAINED; 6412 } 6413 } 6414 return SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNKNOWN; 6415 } 6416 getSupportedSatelliteServicesOnSessionStart(List<Integer> supportedServices)6417 private int[] getSupportedSatelliteServicesOnSessionStart(List<Integer> supportedServices) { 6418 if (supportedServices == null || supportedServices.isEmpty()) { 6419 return new int[0]; 6420 } 6421 6422 return supportedServices.stream().mapToInt(Integer::intValue).toArray(); 6423 } 6424 logCarrierRoamingSatelliteSessionStats(@onNull Phone phone, boolean lastNotifiedNtnMode, boolean currNtnMode)6425 private void logCarrierRoamingSatelliteSessionStats(@NonNull Phone phone, 6426 boolean lastNotifiedNtnMode, boolean currNtnMode) { 6427 synchronized (mSatelliteConnectedLock) { 6428 int subId = phone.getSubId(); 6429 if (!lastNotifiedNtnMode && currNtnMode) { 6430 // Log satellite session start 6431 CarrierRoamingSatelliteSessionStats sessionStats = 6432 CarrierRoamingSatelliteSessionStats.getInstance(subId); 6433 int[] supported_satellite_services = 6434 getSupportedSatelliteServicesOnSessionStart( 6435 getSupportedSatelliteServicesForPlmn(subId, 6436 phone.getServiceState().getOperatorNumeric())); 6437 int dataPolicy = mapDataPolicyForMetrics(getSatelliteDataServicePolicyForPlmn(subId, 6438 phone.getServiceState().getOperatorNumeric())); 6439 6440 sessionStats.onSessionStart(phone.getCarrierId(), phone, 6441 supported_satellite_services, dataPolicy); 6442 mCarrierRoamingSatelliteSessionStatsMap.put(subId, sessionStats); 6443 mCarrierRoamingSatelliteControllerStats.onSessionStart(subId); 6444 } else if (lastNotifiedNtnMode && !currNtnMode) { 6445 // Log satellite session end 6446 CarrierRoamingSatelliteSessionStats sessionStats = 6447 mCarrierRoamingSatelliteSessionStatsMap.get(subId); 6448 sessionStats.onSessionEnd(subId); 6449 mCarrierRoamingSatelliteSessionStatsMap.remove(subId); 6450 mCarrierRoamingSatelliteControllerStats.onSessionEnd(subId); 6451 } 6452 } 6453 } 6454 evaluateCarrierRoamingNtnEligibilityChange()6455 private void evaluateCarrierRoamingNtnEligibilityChange() { 6456 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 6457 plogd("evaluateCarrierRoamingNtnEligibilityChange: " 6458 + "carrierRoamingNbIotNtn flag is disabled"); 6459 return; 6460 } 6461 6462 registerForSatelliteCommunicationAccessStateChanged(); 6463 6464 if (isSatelliteEnabledOrBeingEnabled()) { 6465 plogd("evaluateCarrierRoamingNtnEligibilityChange: " 6466 + "Skip eligibility check as satellite is enabled or being enabled"); 6467 return; 6468 } 6469 6470 boolean eligible = isCarrierRoamingNtnEligible(getSatellitePhone()); 6471 plogd("evaluateCarrierRoamingNtnEligibilityChange: " 6472 + "isCarrierRoamingNtnEligible=" + eligible); 6473 6474 if (eligible) { 6475 if (shouldStartNtnEligibilityHysteresisTimer(eligible)) { 6476 startNtnEligibilityHysteresisTimer(); 6477 } 6478 } else { 6479 stopNtnEligibilityHysteresisTimer(); 6480 updateLastNotifiedNtnEligibilityAndNotify(false); 6481 } 6482 } 6483 shouldStartNtnEligibilityHysteresisTimer(boolean eligible)6484 private boolean shouldStartNtnEligibilityHysteresisTimer(boolean eligible) { 6485 if (!eligible) { 6486 return false; 6487 } 6488 6489 if (hasMessages(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT)) { 6490 plogd("shouldStartNtnEligibilityHysteresisTimer: Timer is already running."); 6491 return false; 6492 } 6493 6494 synchronized (mSatellitePhoneLock) { 6495 if (mLastNotifiedNtnEligibility != null && mLastNotifiedNtnEligibility) { 6496 return false; 6497 } 6498 } 6499 6500 return true; 6501 } 6502 startNtnEligibilityHysteresisTimer()6503 private void startNtnEligibilityHysteresisTimer() { 6504 Phone satellitePhone = getSatellitePhone(); 6505 if (satellitePhone == null) { 6506 ploge("startNtnEligibilityHysteresisTimer: mSatellitePhone is null."); 6507 return; 6508 } 6509 6510 int subId = getSelectedSatelliteSubId(); 6511 long timeout = getCarrierSupportedSatelliteNotificationHysteresisTimeMillis(subId); 6512 plogd("startNtnEligibilityHysteresisTimer: sendMessageDelayed subId=" + subId 6513 + ", phoneId=" + satellitePhone.getPhoneId() + ", timeout=" + timeout); 6514 sendMessageDelayed(obtainMessage(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT), 6515 timeout); 6516 6517 } 6518 stopNtnEligibilityHysteresisTimer()6519 private void stopNtnEligibilityHysteresisTimer() { 6520 if (hasMessages(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT)) { 6521 removeMessages(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT); 6522 } 6523 } 6524 updateLastNotifiedNtnEligibilityAndNotify(boolean currentNtnEligibility)6525 private void updateLastNotifiedNtnEligibilityAndNotify(boolean currentNtnEligibility) { 6526 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 6527 plogd("notifyNtnEligibility: carrierRoamingNbIotNtn flag is disabled"); 6528 return; 6529 } 6530 6531 Phone satellitePhone = getSatellitePhone(); 6532 if (satellitePhone == null) { 6533 ploge("notifyNtnEligibility: mSatellitePhone is null"); 6534 return; 6535 } 6536 6537 if (mOverrideNtnEligibility != null) { 6538 satellitePhone.notifyCarrierRoamingNtnEligibleStateChanged(currentNtnEligibility); 6539 return; 6540 } 6541 6542 int selectedSatelliteSubId = getSelectedSatelliteSubId(); 6543 synchronized (mSatellitePhoneLock) { 6544 plogd("notifyNtnEligibility: phoneId=" + satellitePhone.getPhoneId() 6545 + " currentNtnEligibility=" + currentNtnEligibility); 6546 if (mLastNotifiedNtnEligibility == null 6547 || mLastNotifiedNtnEligibility != currentNtnEligibility) { 6548 mLastNotifiedNtnEligibility = currentNtnEligibility; 6549 satellitePhone.notifyCarrierRoamingNtnEligibleStateChanged(currentNtnEligibility); 6550 updateSatelliteSystemNotification(selectedSatelliteSubId, 6551 CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL, 6552 currentNtnEligibility); 6553 } 6554 } 6555 } 6556 6557 /** Return last notified ntn eligibility. */ getLastNotifiedNtnEligibility(@onNull Phone phone)6558 public boolean getLastNotifiedNtnEligibility(@NonNull Phone phone) { 6559 int selectedSatelliteSubId = getSelectedSatelliteSubId(); 6560 int subId = phone.getSubId(); 6561 if (subId != selectedSatelliteSubId) { 6562 plogd("getLastNotifiedNtnEligibility: subId=" + subId 6563 + " does not match selectedSatelliteSubId=" + selectedSatelliteSubId); 6564 return false; 6565 } 6566 6567 synchronized (mSatellitePhoneLock) { 6568 plogd("getLastNotifiedNtnEligibility: return " + mLastNotifiedNtnEligibility); 6569 return mLastNotifiedNtnEligibility; 6570 } 6571 } 6572 getSatelliteConnectionHysteresisTimeMillis(int subId)6573 private long getSatelliteConnectionHysteresisTimeMillis(int subId) { 6574 PersistableBundle config = getPersistableBundle(subId); 6575 return (config.getInt( 6576 KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT) * 1000L); 6577 } 6578 getCarrierSupportedSatelliteNotificationHysteresisTimeMillis(int subId)6579 private long getCarrierSupportedSatelliteNotificationHysteresisTimeMillis(int subId) { 6580 PersistableBundle config = getPersistableBundle(subId); 6581 return (config.getInt( 6582 KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT) * 1000L); 6583 } 6584 persistOemEnabledSatelliteProvisionStatus(boolean isProvisioned)6585 private void persistOemEnabledSatelliteProvisionStatus(boolean isProvisioned) { 6586 synchronized (mDeviceProvisionLock) { 6587 plogd("persistOemEnabledSatelliteProvisionStatus: isProvisioned=" + isProvisioned); 6588 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 6589 int subId = getNtnOnlySubscriptionId(); 6590 if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 6591 try { 6592 mSubscriptionManagerService.setIsSatelliteProvisionedForNonIpDatagram(subId, 6593 isProvisioned); 6594 plogd("persistOemEnabledSatelliteProvisionStatus: subId=" + subId); 6595 } catch (IllegalArgumentException | SecurityException ex) { 6596 ploge("setIsSatelliteProvisionedForNonIpDatagram: subId=" + subId + ", ex=" 6597 + ex); 6598 } 6599 } else { 6600 plogd("persistOemEnabledSatelliteProvisionStatus: INVALID_SUBSCRIPTION_ID"); 6601 } 6602 } else { 6603 if (!loadSatelliteSharedPreferences()) return; 6604 6605 if (mSharedPreferences == null) { 6606 ploge("persistOemEnabledSatelliteProvisionStatus: mSharedPreferences is null"); 6607 } else { 6608 mSharedPreferences.edit().putBoolean( 6609 OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY, isProvisioned).apply(); 6610 } 6611 } 6612 } 6613 } 6614 6615 @Nullable getPersistedDeviceProvisionStatus()6616 private boolean getPersistedDeviceProvisionStatus() { 6617 plogd("getPersistedDeviceProvisionStatus"); 6618 synchronized (mDeviceProvisionLock) { 6619 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 6620 int subId = getNtnOnlySubscriptionId(); 6621 if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 6622 if (mSubscriptionManagerService.isSatelliteProvisionedForNonIpDatagram(subId)) { 6623 return true; 6624 } 6625 } 6626 6627 List<SubscriptionInfo> activeSubscriptionInfoList = 6628 mSubscriptionManagerService.getActiveSubscriptionInfoList( 6629 mContext.getOpPackageName(), mContext.getAttributionTag(), true); 6630 for (SubscriptionInfo info : activeSubscriptionInfoList) { 6631 if (info.isSatelliteESOSSupported()) { 6632 if (mSubscriptionManagerService.isSatelliteProvisionedForNonIpDatagram( 6633 info.getSubscriptionId())) { 6634 Pair<String, Integer> subscriberIdPair = getSubscriberIdAndType( 6635 mSubscriptionManagerService.getSubscriptionInfo(subId)); 6636 String subscriberId = subscriberIdPair.first; 6637 synchronized (mSatelliteTokenProvisionedLock) { 6638 mProvisionedSubscriberId.put(subscriberId, true); 6639 } 6640 return true; 6641 } 6642 } 6643 } 6644 return false; 6645 } else { 6646 if (!loadSatelliteSharedPreferences()) return false; 6647 6648 if (mSharedPreferences == null) { 6649 ploge("getPersistedDeviceProvisionStatus: mSharedPreferences is " 6650 + "null"); 6651 return false; 6652 } else { 6653 return mSharedPreferences.getBoolean( 6654 OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY, false); 6655 } 6656 } 6657 } 6658 } 6659 loadSatelliteSharedPreferences()6660 private boolean loadSatelliteSharedPreferences() { 6661 if (mSharedPreferences == null) { 6662 try { 6663 mSharedPreferences = 6664 mContext.getSharedPreferences(SATELLITE_SHARED_PREF, 6665 Context.MODE_PRIVATE); 6666 } catch (Exception e) { 6667 ploge("loadSatelliteSharedPreferences: Cannot get default " 6668 + "shared preferences, e=" + e); 6669 return false; 6670 } 6671 } 6672 return true; 6673 } 6674 handleIsSatelliteProvisionedDoneEvent(@onNull AsyncResult ar)6675 private void handleIsSatelliteProvisionedDoneEvent(@NonNull AsyncResult ar) { 6676 logd("handleIsSatelliteProvisionedDoneEvent:"); 6677 SatelliteControllerHandlerRequest request = (SatelliteControllerHandlerRequest) ar.userObj; 6678 6679 Bundle bundle = new Bundle(); 6680 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED, 6681 Boolean.TRUE.equals(isDeviceProvisioned())); 6682 ((ResultReceiver) request.argument).send(SATELLITE_RESULT_SUCCESS, bundle); 6683 decrementResultReceiverCount("SC:requestIsSatelliteProvisioned"); 6684 } 6685 getWaitForSatelliteEnablingResponseTimeoutMillis()6686 private long getWaitForSatelliteEnablingResponseTimeoutMillis() { 6687 return mContext.getResources().getInteger( 6688 R.integer.config_wait_for_satellite_enabling_response_timeout_millis); 6689 } 6690 getWaitForCellularModemOffTimeoutMillis()6691 private long getWaitForCellularModemOffTimeoutMillis() { 6692 return mContext.getResources().getInteger( 6693 R.integer.config_satellite_wait_for_cellular_modem_off_timeout_millis); 6694 } 6695 startWaitForCellularModemOffTimer()6696 private void startWaitForCellularModemOffTimer() { 6697 synchronized (mIsRadioOnLock) { 6698 if (hasMessages(EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT)) { 6699 plogd("startWaitForCellularModemOffTimer: the timer was already started"); 6700 return; 6701 } 6702 long timeoutMillis = getWaitForCellularModemOffTimeoutMillis(); 6703 plogd("Start timer to wait for cellular modem OFF state, timeoutMillis=" 6704 + timeoutMillis); 6705 sendMessageDelayed(obtainMessage(EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT), 6706 timeoutMillis); 6707 } 6708 } 6709 stopWaitForCellularModemOffTimer()6710 private void stopWaitForCellularModemOffTimer() { 6711 synchronized (mSatelliteEnabledRequestLock) { 6712 plogd("Stop timer to wait for cellular modem OFF state"); 6713 removeMessages(EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT); 6714 } 6715 } 6716 startWaitForSatelliteEnablingResponseTimer( @onNull RequestSatelliteEnabledArgument argument)6717 private void startWaitForSatelliteEnablingResponseTimer( 6718 @NonNull RequestSatelliteEnabledArgument argument) { 6719 synchronized (mSatelliteEnabledRequestLock) { 6720 if (hasMessages(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT, argument)) { 6721 plogd("WaitForSatelliteEnablingResponseTimer of request ID " 6722 + argument.requestId + " was already started"); 6723 return; 6724 } 6725 plogd("Start timer to wait for response of the satellite enabling request ID=" 6726 + argument.requestId + ", enableSatellite=" + argument.enableSatellite 6727 + ", mWaitTimeForSatelliteEnablingResponse=" 6728 + mWaitTimeForSatelliteEnablingResponse); 6729 sendMessageDelayed(obtainMessage(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT, 6730 argument), mWaitTimeForSatelliteEnablingResponse); 6731 } 6732 } 6733 stopWaitForSatelliteEnablingResponseTimer( @onNull RequestSatelliteEnabledArgument argument)6734 private void stopWaitForSatelliteEnablingResponseTimer( 6735 @NonNull RequestSatelliteEnabledArgument argument) { 6736 synchronized (mSatelliteEnabledRequestLock) { 6737 plogd("Stop timer to wait for response of the satellite enabling request ID=" 6738 + argument.requestId + ", enableSatellite=" + argument.enableSatellite); 6739 removeMessages(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT, argument); 6740 } 6741 } 6742 shouldProcessEventSetSatelliteEnabledDone( @onNull RequestSatelliteEnabledArgument argument)6743 private boolean shouldProcessEventSetSatelliteEnabledDone( 6744 @NonNull RequestSatelliteEnabledArgument argument) { 6745 synchronized (mSatelliteEnabledRequestLock) { 6746 if (hasMessages(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT, argument)) { 6747 return true; 6748 } 6749 return false; 6750 } 6751 } 6752 startWaitForUpdateSystemSelectionChannelsResponseTimer( @onNull UpdateSystemSelectionChannelsArgument argument)6753 private void startWaitForUpdateSystemSelectionChannelsResponseTimer( 6754 @NonNull UpdateSystemSelectionChannelsArgument argument) { 6755 synchronized (mSatelliteEnabledRequestLock) { 6756 if (hasMessages( 6757 EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT, argument)) { 6758 plogd("WaitForUpdateSystemSelectionChannelsResponseTimer of request ID " 6759 + argument.requestId + " was already started"); 6760 return; 6761 } 6762 plogd("Start timer to wait for response of the system selection channels update request" 6763 + " ID=" + argument.requestId + ", mWaitTimeForSatelliteEnablingResponse=" 6764 + mWaitTimeForSatelliteEnablingResponse); 6765 sendMessageDelayed( 6766 obtainMessage(EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT, 6767 argument), mWaitTimeForSatelliteEnablingResponse); 6768 } 6769 } 6770 stopWaitForUpdateSystemSelectionChannelsResponseTimer( @onNull UpdateSystemSelectionChannelsArgument argument)6771 private void stopWaitForUpdateSystemSelectionChannelsResponseTimer( 6772 @NonNull UpdateSystemSelectionChannelsArgument argument) { 6773 synchronized (mSatelliteEnabledRequestLock) { 6774 plogd("Stop timer to wait for response of the system selection channels" 6775 + " update request ID=" + argument.requestId); 6776 removeMessages( 6777 EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT, argument); 6778 } 6779 } 6780 shouldProcessEventUpdateSystemSelectionChannelsDone( @onNull UpdateSystemSelectionChannelsArgument argument)6781 private boolean shouldProcessEventUpdateSystemSelectionChannelsDone( 6782 @NonNull UpdateSystemSelectionChannelsArgument argument) { 6783 synchronized (mSatelliteEnabledRequestLock) { 6784 if (hasMessages( 6785 EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT, argument)) { 6786 return true; 6787 } 6788 return false; 6789 } 6790 } 6791 startWaitForUpdateSatelliteEnableAttributesResponseTimer( @onNull RequestSatelliteEnabledArgument argument)6792 private void startWaitForUpdateSatelliteEnableAttributesResponseTimer( 6793 @NonNull RequestSatelliteEnabledArgument argument) { 6794 synchronized (mSatelliteEnabledRequestLock) { 6795 if (hasMessages(EVENT_WAIT_FOR_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_RESPONSE_TIMED_OUT, 6796 argument)) { 6797 plogd("WaitForUpdateSatelliteEnableAttributesResponseTimer of request ID " 6798 + argument.requestId + " was already started"); 6799 return; 6800 } 6801 plogd("Start timer to wait for response of the update satellite enable attributes" 6802 + " request ID=" + argument.requestId 6803 + ", enableSatellite=" + argument.enableSatellite 6804 + ", mWaitTimeForSatelliteEnablingResponse=" 6805 + mWaitTimeForSatelliteEnablingResponse); 6806 sendMessageDelayed(obtainMessage( 6807 EVENT_WAIT_FOR_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_RESPONSE_TIMED_OUT, 6808 argument), mWaitTimeForSatelliteEnablingResponse); 6809 } 6810 } 6811 stopWaitForUpdateSatelliteEnableAttributesResponseTimer( @onNull RequestSatelliteEnabledArgument argument)6812 private void stopWaitForUpdateSatelliteEnableAttributesResponseTimer( 6813 @NonNull RequestSatelliteEnabledArgument argument) { 6814 synchronized (mSatelliteEnabledRequestLock) { 6815 plogd("Stop timer to wait for response of the enable attributes update request ID=" 6816 + argument.requestId + ", enableSatellite=" + argument.enableSatellite); 6817 removeMessages( 6818 EVENT_WAIT_FOR_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_RESPONSE_TIMED_OUT, argument); 6819 } 6820 } 6821 shouldProcessEventUpdateSatelliteEnableAttributesDone( @onNull RequestSatelliteEnabledArgument argument)6822 private boolean shouldProcessEventUpdateSatelliteEnableAttributesDone( 6823 @NonNull RequestSatelliteEnabledArgument argument) { 6824 synchronized (mSatelliteEnabledRequestLock) { 6825 if (hasMessages(EVENT_WAIT_FOR_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_RESPONSE_TIMED_OUT, 6826 argument)) { 6827 return true; 6828 } 6829 return false; 6830 } 6831 } 6832 handleEventWaitForSatelliteEnablingResponseTimedOut( @onNull RequestSatelliteEnabledArgument argument)6833 private void handleEventWaitForSatelliteEnablingResponseTimedOut( 6834 @NonNull RequestSatelliteEnabledArgument argument) { 6835 plogw("Timed out to wait for response of the satellite enabling request ID=" 6836 + argument.requestId + ", enableSatellite=" + argument.enableSatellite); 6837 6838 argument.callback.accept(SATELLITE_RESULT_MODEM_TIMEOUT); 6839 if (argument.enableSatellite) { 6840 resetSatelliteEnabledRequest(); 6841 abortSatelliteEnableAttributesUpdateRequest(SATELLITE_RESULT_REQUEST_ABORTED); 6842 if (getSatelliteDisabledRequest() == null) { 6843 IIntegerConsumer callback = new IIntegerConsumer.Stub() { 6844 @Override 6845 public void accept(int result) { 6846 plogd("handleEventWaitForSatelliteEnablingResponseTimedOut: " 6847 + "disable satellite result=" + result); 6848 } 6849 }; 6850 Consumer<Integer> result = 6851 FunctionalUtils.ignoreRemoteException(callback::accept); 6852 6853 RequestSatelliteEnabledArgument request; 6854 synchronized (mSatelliteEnabledRequestLock) { 6855 mSatelliteDisabledRequest = new RequestSatelliteEnabledArgument( 6856 false, false, false, result); 6857 request = mSatelliteDisabledRequest; 6858 } 6859 6860 sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null); 6861 } 6862 6863 mControllerMetricsStats.reportServiceEnablementFailCount(); 6864 mSessionMetricsStats.setInitializationResult(SATELLITE_RESULT_MODEM_TIMEOUT) 6865 .setSatelliteTechnology(getSupportedNtnRadioTechnology()) 6866 .setInitializationProcessingTime( 6867 getElapsedRealtime() - mSessionProcessingTimeStamp) 6868 .setIsDemoMode(mIsDemoModeEnabled) 6869 .setCarrierId(getSatelliteCarrierId()) 6870 .reportSessionMetrics(); 6871 } else { 6872 resetSatelliteDisabledRequest(); 6873 mControllerMetricsStats.onSatelliteDisabled(); 6874 mSessionMetricsStats.setTerminationResult(SATELLITE_RESULT_MODEM_TIMEOUT) 6875 .setSatelliteTechnology(getSupportedNtnRadioTechnology()) 6876 .setTerminationProcessingTime( 6877 getElapsedRealtime() - mSessionProcessingTimeStamp) 6878 .setSessionDurationSec(calculateSessionDurationTimeSec()) 6879 .reportSessionMetrics(); 6880 } 6881 notifyEnablementFailedToSatelliteSessionController(argument.enableSatellite); 6882 mSessionStartTimeStamp = 0; 6883 mSessionProcessingTimeStamp = 0; 6884 } 6885 handleCmdUpdateNtnSignalStrengthReporting(boolean shouldReport)6886 private void handleCmdUpdateNtnSignalStrengthReporting(boolean shouldReport) { 6887 if (!isSatelliteEnabledOrBeingEnabled()) { 6888 plogd("handleCmdUpdateNtnSignalStrengthReporting: ignore request, satellite is " 6889 + "disabled"); 6890 return; 6891 } 6892 6893 mLatestRequestedStateForNtnSignalStrengthReport.set(shouldReport); 6894 if (mIsModemEnabledReportingNtnSignalStrength.get() == shouldReport) { 6895 plogd("handleCmdUpdateNtnSignalStrengthReporting: ignore request. " 6896 + "mIsModemEnabledReportingNtnSignalStrength=" 6897 + mIsModemEnabledReportingNtnSignalStrength.get()); 6898 return; 6899 } 6900 6901 updateNtnSignalStrengthReporting(shouldReport); 6902 } 6903 updateNtnSignalStrengthReporting(boolean shouldReport)6904 private void updateNtnSignalStrengthReporting(boolean shouldReport) { 6905 SatelliteControllerHandlerRequest request = new SatelliteControllerHandlerRequest( 6906 shouldReport, SatelliteServiceUtils.getPhone()); 6907 Message onCompleted = obtainMessage(EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE, 6908 request); 6909 if (shouldReport) { 6910 plogd("updateNtnSignalStrengthReporting: startSendingNtnSignalStrength"); 6911 mSatelliteModemInterface.startSendingNtnSignalStrength(onCompleted); 6912 } else { 6913 plogd("updateNtnSignalStrengthReporting: stopSendingNtnSignalStrength"); 6914 mSatelliteModemInterface.stopSendingNtnSignalStrength(onCompleted); 6915 } 6916 } 6917 6918 /** 6919 * This API can be used by only CTS to override the cached value for the device overlay config 6920 * value : config_send_satellite_datagram_to_modem_in_demo_mode, which determines whether 6921 * outgoing satellite datagrams should be sent to modem in demo mode. 6922 * 6923 * @param shouldSendToModemInDemoMode Whether send datagram in demo mode should be sent to 6924 * satellite modem or not. 6925 * 6926 * @return {@code true} if the operation is successful, {@code false} otherwise. 6927 */ setShouldSendDatagramToModemInDemoMode(boolean shouldSendToModemInDemoMode)6928 public boolean setShouldSendDatagramToModemInDemoMode(boolean shouldSendToModemInDemoMode) { 6929 if (!isMockModemAllowed()) { 6930 plogd("setShouldSendDatagramToModemInDemoMode: mock modem not allowed."); 6931 return false; 6932 } 6933 6934 mDatagramController.setShouldSendDatagramToModemInDemoMode(shouldSendToModemInDemoMode); 6935 return true; 6936 } 6937 determineAutoConnectSystemNotification()6938 private void determineAutoConnectSystemNotification() { 6939 Pair<Boolean, Integer> isNtn = isUsingNonTerrestrialNetworkViaCarrier(); 6940 boolean suppressSatelliteNotification = mSharedPreferences.getBoolean( 6941 SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false); 6942 if (suppressSatelliteNotification) { 6943 // System already displayed the notification and user interacted with it. 6944 // System will show notification again after 30 days. 6945 long lastSetTimestamp = mSharedPreferences.getLong( 6946 SATELLITE_SYSTEM_NOTIFICATION_TIME, 0L); 6947 logv("determineAutoConnectSystemNotification lastSetTimestamp = " + lastSetTimestamp); 6948 long currentTime = System.currentTimeMillis(); 6949 int subId = getSelectedSatelliteSubId(); 6950 long throttleTime = getNotificationDisplayThrottleTimeout(subId); 6951 if (lastSetTimestamp == 0L || currentTime - lastSetTimestamp >= throttleTime) { 6952 // Reset the flag and update the timestamp 6953 logd("determineAutoConnectSystemNotification: reset preference data"); 6954 suppressSatelliteNotification = false; 6955 mSharedPreferences.edit().putBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, 6956 false).remove(SATELLITE_SYSTEM_NOTIFICATION_TIME).apply(); 6957 } 6958 } 6959 if (DEBUG) { 6960 logd("determineAutoConnectSystemNotification: isNtn.first = " + isNtn.first 6961 + " IsNotiToShow = " + !suppressSatelliteNotification 6962 + " mIsNotificationShowing = " + mIsNotificationShowing); 6963 } 6964 if (isNtn.first) { 6965 if (!suppressSatelliteNotification && getCarrierRoamingNtnConnectType(isNtn.second) 6966 == CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC) { 6967 updateSatelliteSystemNotification(isNtn.second, 6968 CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC, 6969 /*visible*/ true); 6970 } 6971 } else if (mIsNotificationShowing 6972 && !isSatelliteConnectedViaCarrierWithinHysteresisTime().first) { 6973 // Dismiss the notification if it is still displaying. 6974 dismissSatelliteNotification(); 6975 } 6976 } 6977 dismissSatelliteNotification()6978 private void dismissSatelliteNotification() { 6979 mIsNotificationShowing = false; 6980 updateSatelliteSystemNotification(-1, -1,/*visible*/ false); 6981 } 6982 isSatelliteSystemNotificationsEnabled(int carrierRoamingNtnConnectType)6983 public boolean isSatelliteSystemNotificationsEnabled(int carrierRoamingNtnConnectType) { 6984 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 6985 return false; 6986 } 6987 if (carrierRoamingNtnConnectType 6988 != CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL) { 6989 return true; 6990 } 6991 boolean notifySatelliteAvailabilityEnabled = 6992 mContext.getResources().getBoolean(R.bool.config_satellite_should_notify_availability); 6993 Boolean isSatelliteSupported = getIsSatelliteSupported(); 6994 if(isSatelliteSupported == null) { 6995 return false; 6996 } 6997 int subId = getSelectedSatelliteSubId(); 6998 SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(subId); 6999 logd("isSatelliteSystemNotificationsEnabled: SatelliteSubId = " + subId); 7000 return notifySatelliteAvailabilityEnabled 7001 && isSatelliteSupported 7002 && isValidSubscriptionId(subId) 7003 && ((isSatelliteSupportedViaCarrier(subId) 7004 && (getCarrierRoamingNtnConnectType(subId) 7005 == CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL)) 7006 || subInfo.isOnlyNonTerrestrialNetwork()); 7007 } 7008 isDataServiceSupported(int subId)7009 private boolean isDataServiceSupported(int subId) { 7010 int[] services = getSupportedServicesOnCarrierRoamingNtn(subId); 7011 return ArrayUtils.contains(services, NetworkRegistrationInfo.SERVICE_TYPE_DATA); 7012 } 7013 7014 /** 7015 * Update the system notification to reflect the current satellite status, that's either already 7016 * connected OR needs to be manually enabled. The device should only display one notification 7017 * at a time to prevent confusing the user, so the same NOTIFICATION_CHANNEL and NOTIFICATION_ID 7018 * are used. 7019 * 7020 * @param subId The subId that provides the satellite connection. 7021 * @param carrierRoamingNtnConnectType {@link CarrierConfigManager 7022 * .CARRIER_ROAMING_NTN_CONNECT_TYPE} 7023 * @param visible {@code true} to show the notification, {@code false} to cancel it. 7024 */ updateSatelliteSystemNotification(int subId, @CARRIER_ROAMING_NTN_CONNECT_TYPE int carrierRoamingNtnConnectType, boolean visible)7025 private void updateSatelliteSystemNotification(int subId, 7026 @CARRIER_ROAMING_NTN_CONNECT_TYPE int carrierRoamingNtnConnectType, boolean visible) { 7027 if (!isSatelliteSystemNotificationsEnabled(carrierRoamingNtnConnectType)) { 7028 plogd("updateSatelliteSystemNotification: satellite notifications are not enabled."); 7029 return; 7030 } 7031 7032 plogd("updateSatelliteSystemNotification subId=" + subId + ", carrierRoamingNtnConnectType=" 7033 + SatelliteServiceUtils.carrierRoamingNtnConnectTypeToString( 7034 carrierRoamingNtnConnectType) + ", visible=" + visible); 7035 final NotificationChannel notificationChannel = new NotificationChannel( 7036 NOTIFICATION_CHANNEL_ID, 7037 NOTIFICATION_CHANNEL, 7038 NotificationManager.IMPORTANCE_DEFAULT); 7039 notificationChannel.setSound(null, null); 7040 NotificationManager notificationManager = mContext.getSystemService( 7041 NotificationManager.class); 7042 if (notificationManager == null) { 7043 ploge("updateSatelliteSystemNotification: notificationManager is null"); 7044 return; 7045 } 7046 if (!visible) { // Cancel if any. 7047 notificationManager.cancelAsUser(NOTIFICATION_TAG, NOTIFICATION_ID, UserHandle.ALL); 7048 return; 7049 } 7050 notificationManager.createNotificationChannel(notificationChannel); 7051 7052 int title = R.string.satellite_notification_title; 7053 int summary = R.string.satellite_notification_summary; 7054 if (carrierRoamingNtnConnectType 7055 == CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL) { 7056 title = R.string.satellite_notification_manual_title; 7057 summary = R.string.satellite_notification_manual_summary; 7058 } else if (carrierRoamingNtnConnectType 7059 == CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC 7060 && isDataServiceSupported(subId)) { 7061 // In Auto Connected mode, if data services supported, show data supported summary 7062 summary = R.string.satellite_notification_summary_with_data; 7063 } 7064 7065 Notification.Builder notificationBuilder = new Notification.Builder(mContext, 7066 NOTIFICATION_CHANNEL_ID) 7067 .setContentTitle(mContext.getResources().getString(title)) 7068 .setContentText(mContext.getResources().getString(summary)) 7069 .setSmallIcon(R.drawable.ic_android_satellite_24px) 7070 .setAutoCancel(true) 7071 .setColor(mContext.getColor( 7072 com.android.internal.R.color.system_notification_accent_color)) 7073 .setVisibility(Notification.VISIBILITY_PUBLIC); 7074 7075 // Intent for `Open Messages` [Button 1] 7076 Intent openMessageIntent = new Intent(); 7077 openMessageIntent.setAction(OPEN_MESSAGE_BUTTON); 7078 PendingIntent openMessagePendingIntent = PendingIntent.getBroadcast(mContext, 0, 7079 openMessageIntent, PendingIntent.FLAG_IMMUTABLE); 7080 Notification.Action actionOpenMessage = new Notification.Action.Builder(0, 7081 mContext.getResources().getString(R.string.satellite_notification_open_message), 7082 openMessagePendingIntent).build(); 7083 notificationBuilder.addAction(actionOpenMessage); // Handle `Open Messages` button 7084 7085 // Button for `How it works` [Button 2] 7086 Intent howItWorksIntent = new Intent(); 7087 howItWorksIntent.setAction(HOW_IT_WORKS_BUTTON); 7088 howItWorksIntent.putExtra("SUBID", subId); 7089 PendingIntent howItWorksPendingIntent = PendingIntent.getBroadcast(mContext, 0, 7090 howItWorksIntent, PendingIntent.FLAG_IMMUTABLE); 7091 Notification.Action actionHowItWorks = new Notification.Action.Builder(0, 7092 mContext.getResources().getString(R.string.satellite_notification_how_it_works), 7093 howItWorksPendingIntent).build(); 7094 notificationBuilder.addAction(actionHowItWorks); // Handle `How it works` button 7095 7096 // Intent for clicking the main notification body 7097 Intent notificationClickIntent = new Intent(ACTION_NOTIFICATION_CLICK); 7098 PendingIntent notificationClickPendingIntent = PendingIntent.getBroadcast(mContext, 0, 7099 notificationClickIntent, PendingIntent.FLAG_IMMUTABLE); 7100 notificationBuilder.setContentIntent( 7101 notificationClickPendingIntent); // Handle notification body click 7102 7103 // Intent for dismissing/swiping the notification 7104 Intent deleteIntent = new Intent(ACTION_NOTIFICATION_DISMISS); 7105 PendingIntent deletePendingIntent = PendingIntent.getBroadcast(mContext, 0, deleteIntent, 7106 PendingIntent.FLAG_IMMUTABLE); 7107 notificationBuilder.setDeleteIntent( 7108 deletePendingIntent); // Handle notification swipe/dismiss 7109 7110 notificationManager.notifyAsUser(NOTIFICATION_TAG, NOTIFICATION_ID, 7111 notificationBuilder.build(), UserHandle.ALL); 7112 7113 // The Intent filter is to receive the above four events. 7114 IntentFilter filter = new IntentFilter(); 7115 filter.addAction(OPEN_MESSAGE_BUTTON); 7116 filter.addAction(HOW_IT_WORKS_BUTTON); 7117 filter.addAction(ACTION_NOTIFICATION_CLICK); 7118 filter.addAction(ACTION_NOTIFICATION_DISMISS); 7119 mContext.registerReceiver(mNotificationInteractionBroadcastReceiver, filter, 7120 Context.RECEIVER_EXPORTED); 7121 7122 mIsNotificationShowing = true; 7123 mCarrierRoamingSatelliteControllerStats.reportCountOfSatelliteNotificationDisplayed(subId); 7124 mCarrierRoamingSatelliteControllerStats.reportCarrierId(getSatelliteCarrierId()); 7125 mSessionMetricsStats.addCountOfSatelliteNotificationDisplayed(); 7126 } 7127 7128 private final BroadcastReceiver mNotificationInteractionBroadcastReceiver = 7129 new BroadcastReceiver() { 7130 @Override 7131 public void onReceive(Context context, Intent receivedIntent) { 7132 String intentAction = receivedIntent.getAction(); 7133 if (TextUtils.isEmpty(intentAction)) { 7134 loge("Received empty action from the notification"); 7135 return; 7136 } 7137 if (DBG) { 7138 plogd("Notification Broadcast recvd action = " 7139 + receivedIntent.getAction()); 7140 } 7141 boolean closeStatusBar = true; 7142 switch (intentAction) { 7143 case OPEN_MESSAGE_BUTTON -> { 7144 // Add action to invoke message application. 7145 // getDefaultSmsPackage and getLaunchIntentForPackage are nullable. 7146 Optional<Intent> nullableIntent = Optional.ofNullable( 7147 Telephony.Sms.getDefaultSmsPackage(context)).flatMap( 7148 packageName -> { 7149 PackageManager pm = context.getPackageManager(); 7150 return Optional.ofNullable( 7151 pm.getLaunchIntentForPackage(packageName)); 7152 }); 7153 // If nullableIntent is null, create new Intent for most common way to 7154 // invoke 7155 // message app. 7156 Intent finalIntent = nullableIntent.map(intent -> { 7157 // Invoke the home screen of default message application. 7158 intent.setAction(Intent.ACTION_MAIN); 7159 intent.addCategory(Intent.CATEGORY_HOME); 7160 return intent; 7161 }).orElseGet(() -> { 7162 ploge("showSatelliteSystemNotification: no default sms package " 7163 + "name, Invoke default sms compose window instead"); 7164 Intent newIntent = new Intent(Intent.ACTION_VIEW); 7165 newIntent.setData(Uri.parse("sms:")); 7166 return newIntent; 7167 }); 7168 context.startActivity(finalIntent); 7169 } 7170 case HOW_IT_WORKS_BUTTON -> { 7171 int subId = receivedIntent.getIntExtra("SUBID", -1); 7172 Intent intentSatelliteSetting = new Intent(ACTION_SATELLITE_SETTING); 7173 intentSatelliteSetting.putExtra("sub_id", subId); 7174 intentSatelliteSetting.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 7175 context.startActivity(intentSatelliteSetting); 7176 7177 } 7178 case ACTION_NOTIFICATION_DISMISS -> closeStatusBar = false; 7179 } 7180 // Note : ACTION_NOTIFICATION_DISMISS is not required to handled 7181 dismissNotificationAndUpdatePref(closeStatusBar); 7182 } 7183 }; 7184 dismissNotificationAndUpdatePref(boolean closeStatusBar)7185 private void dismissNotificationAndUpdatePref(boolean closeStatusBar) { 7186 dismissSatelliteNotification(); 7187 if (closeStatusBar) { 7188 // Collapse the status bar once user interact with notification. 7189 StatusBarManager statusBarManager = mContext.getSystemService(StatusBarManager.class); 7190 if (statusBarManager != null) { 7191 statusBarManager.collapsePanels(); 7192 } 7193 } 7194 // update the sharedpref only when user interacted with the notification. 7195 mSharedPreferences.edit().putBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, true).apply(); 7196 mSharedPreferences.edit().putLong(SATELLITE_SYSTEM_NOTIFICATION_TIME, 7197 System.currentTimeMillis()).apply(); 7198 mContext.unregisterReceiver(mNotificationInteractionBroadcastReceiver); 7199 } 7200 resetCarrierRoamingSatelliteModeParams()7201 private void resetCarrierRoamingSatelliteModeParams() { 7202 for (Phone phone : PhoneFactory.getPhones()) { 7203 resetCarrierRoamingSatelliteModeParams(phone.getSubId()); 7204 } 7205 } 7206 resetCarrierRoamingSatelliteModeParams(int subId)7207 private void resetCarrierRoamingSatelliteModeParams(int subId) { 7208 synchronized (mSatelliteConnectedLock) { 7209 mLastSatelliteDisconnectedTimesMillis.put(subId, null); 7210 mSatModeCapabilitiesForCarrierRoaming.remove(subId); 7211 mWasSatelliteConnectedViaCarrier.put(subId, false); 7212 } 7213 } 7214 7215 /** 7216 * Read carrier config items for satellite 7217 * 7218 * @param subId Associated subscription ID 7219 * @return PersistableBundle including carrier config values 7220 */ 7221 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) 7222 @NonNull getPersistableBundle(int subId)7223 public PersistableBundle getPersistableBundle(int subId) { 7224 synchronized (mCarrierConfigArrayLock) { 7225 PersistableBundle config = mCarrierConfigArray.get(subId); 7226 if (config == null) { 7227 config = getConfigForSubId(subId); 7228 mCarrierConfigArray.put(subId, config); 7229 } 7230 return config; 7231 } 7232 } 7233 7234 // Should be invoked only when session termination done or session termination failed. calculateSessionDurationTimeSec()7235 private int calculateSessionDurationTimeSec() { 7236 return (int) ( 7237 (getElapsedRealtime() - mSessionStartTimeStamp 7238 - mSessionMetricsStats.getSessionInitializationProcessingTimeMillis() 7239 - mSessionMetricsStats.getSessionTerminationProcessingTimeMillis()) / 1000); 7240 } 7241 notifyEnablementFailedToSatelliteSessionController(boolean enabled)7242 private void notifyEnablementFailedToSatelliteSessionController(boolean enabled) { 7243 if (mSatelliteSessionController != null) { 7244 mSatelliteSessionController.onSatelliteEnablementFailed(enabled); 7245 } else { 7246 ploge("notifyEnablementFailedToSatelliteSessionController: mSatelliteSessionController" 7247 + " is not initialized yet"); 7248 } 7249 } 7250 abortSatelliteEnableRequest(@atelliteManager.SatelliteResult int resultCode)7251 private void abortSatelliteEnableRequest(@SatelliteManager.SatelliteResult int resultCode) { 7252 synchronized (mSatelliteEnabledRequestLock) { 7253 if (mSatelliteEnabledRequest != null) { 7254 plogw("abortSatelliteEnableRequest"); 7255 if (resultCode == SATELLITE_RESULT_SUCCESS) { 7256 resultCode = SATELLITE_RESULT_REQUEST_ABORTED; 7257 } 7258 mSatelliteEnabledRequest.callback.accept(resultCode); 7259 stopWaitForSatelliteEnablingResponseTimer(mSatelliteEnabledRequest); 7260 mSatelliteEnabledRequest = null; 7261 } 7262 } 7263 } 7264 abortSatelliteDisableRequest(@atelliteManager.SatelliteResult int resultCode)7265 private void abortSatelliteDisableRequest(@SatelliteManager.SatelliteResult int resultCode) { 7266 synchronized (mSatelliteEnabledRequestLock) { 7267 if (mSatelliteDisabledRequest != null) { 7268 plogd("abortSatelliteDisableRequest"); 7269 mSatelliteDisabledRequest.callback.accept(resultCode); 7270 stopWaitForSatelliteEnablingResponseTimer(mSatelliteDisabledRequest); 7271 mSatelliteDisabledRequest = null; 7272 } 7273 } 7274 } 7275 abortSatelliteEnableAttributesUpdateRequest( @atelliteManager.SatelliteResult int resultCode)7276 private void abortSatelliteEnableAttributesUpdateRequest( 7277 @SatelliteManager.SatelliteResult int resultCode) { 7278 synchronized (mSatelliteEnabledRequestLock) { 7279 if (mSatelliteEnableAttributesUpdateRequest != null) { 7280 plogd("abortSatelliteEnableAttributesUpdateRequest"); 7281 if (resultCode == SATELLITE_RESULT_SUCCESS) { 7282 resultCode = SATELLITE_RESULT_REQUEST_ABORTED; 7283 } 7284 mSatelliteEnableAttributesUpdateRequest.callback.accept(resultCode); 7285 stopWaitForUpdateSatelliteEnableAttributesResponseTimer( 7286 mSatelliteEnableAttributesUpdateRequest); 7287 mSatelliteEnableAttributesUpdateRequest = null; 7288 } 7289 } 7290 } 7291 stopWaitForEnableResponseTimers()7292 private void stopWaitForEnableResponseTimers() { 7293 plogd("stopWaitForEnableResponseTimers"); 7294 removeMessages(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT); 7295 } 7296 getDemoPointingAlignedDurationMillisFromResources()7297 private long getDemoPointingAlignedDurationMillisFromResources() { 7298 long durationMillis = 15000L; 7299 try { 7300 durationMillis = mContext.getResources().getInteger( 7301 R.integer.config_demo_pointing_aligned_duration_millis); 7302 } catch (Resources.NotFoundException ex) { 7303 loge("getPointingAlignedDurationMillis: ex=" + ex); 7304 } 7305 7306 return durationMillis; 7307 } 7308 7309 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) getDemoPointingAlignedDurationMillis()7310 public long getDemoPointingAlignedDurationMillis() { 7311 return mDemoPointingAlignedDurationMillis; 7312 } 7313 getDemoPointingNotAlignedDurationMillisFromResources()7314 private long getDemoPointingNotAlignedDurationMillisFromResources() { 7315 long durationMillis = 30000L; 7316 try { 7317 durationMillis = mContext.getResources().getInteger( 7318 R.integer.config_demo_pointing_not_aligned_duration_millis); 7319 } catch (Resources.NotFoundException ex) { 7320 loge("getPointingNotAlignedDurationMillis: ex=" + ex); 7321 } 7322 7323 return durationMillis; 7324 } 7325 7326 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) getDemoPointingNotAlignedDurationMillis()7327 public long getDemoPointingNotAlignedDurationMillis() { 7328 return mDemoPointingNotAlignedDurationMillis; 7329 } 7330 7331 /** Returns {@code true} if WWAN is in service, else {@code false}.*/ 7332 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) getWwanIsInService(@onNull ServiceState serviceState)7333 public boolean getWwanIsInService(@NonNull ServiceState serviceState) { 7334 List<NetworkRegistrationInfo> nriList = serviceState 7335 .getNetworkRegistrationInfoListForTransportType( 7336 AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 7337 7338 for (NetworkRegistrationInfo nri : nriList) { 7339 if (nri.isInService()) { 7340 logv("getWwanIsInService: return true"); 7341 return true; 7342 } 7343 } 7344 7345 logv("getWwanIsInService: return false"); 7346 return false; 7347 } 7348 logv(@onNull String log)7349 private static void logv(@NonNull String log) { 7350 Log.v(TAG, log); 7351 } 7352 logd(@onNull String log)7353 private static void logd(@NonNull String log) { 7354 Log.d(TAG, log); 7355 } 7356 logw(@onNull String log)7357 private static void logw(@NonNull String log) { 7358 Log.w(TAG, log); 7359 } 7360 loge(@onNull String log)7361 private static void loge(@NonNull String log) { 7362 Log.e(TAG, log); 7363 } 7364 plogd(@onNull String log)7365 private void plogd(@NonNull String log) { 7366 Log.d(TAG, log); 7367 if (mPersistentLogger != null) { 7368 mPersistentLogger.debug(TAG, log); 7369 } 7370 } 7371 plogw(@onNull String log)7372 private void plogw(@NonNull String log) { 7373 Log.w(TAG, log); 7374 if (mPersistentLogger != null) { 7375 mPersistentLogger.warn(TAG, log); 7376 } 7377 } 7378 ploge(@onNull String log)7379 private void ploge(@NonNull String log) { 7380 Log.e(TAG, log); 7381 if (mPersistentLogger != null) { 7382 mPersistentLogger.error(TAG, log); 7383 } 7384 } 7385 plogv(@onNull String log)7386 private void plogv(@NonNull String log) { 7387 Log.v(TAG, log); 7388 if (mPersistentLogger != null) { 7389 mPersistentLogger.debug(TAG, log); 7390 } 7391 } 7392 handlePersistentLoggingOnSessionStart(RequestSatelliteEnabledArgument argument)7393 private void handlePersistentLoggingOnSessionStart(RequestSatelliteEnabledArgument argument) { 7394 if (mPersistentLogger == null) { 7395 return; 7396 } 7397 if (argument.isEmergency) { 7398 DropBoxManagerLoggerBackend.getInstance(mContext).setLoggingEnabled(true); 7399 } 7400 } 7401 handlePersistentLoggingOnSessionEnd(boolean isEmergency)7402 private void handlePersistentLoggingOnSessionEnd(boolean isEmergency) { 7403 if (mPersistentLogger == null) { 7404 return; 7405 } 7406 DropBoxManagerLoggerBackend loggerBackend = 7407 DropBoxManagerLoggerBackend.getInstance(mContext); 7408 // Flush persistent satellite logs on eSOS session end 7409 if (isEmergency) { 7410 loggerBackend.flushAsync(); 7411 } 7412 // Also turn off persisted logging until new session is started 7413 loggerBackend.setLoggingEnabled(false); 7414 } 7415 7416 /** 7417 * Set last emergency call time to the current time. 7418 */ setLastEmergencyCallTime()7419 public void setLastEmergencyCallTime() { 7420 synchronized (mLock) { 7421 mLastEmergencyCallTime = getElapsedRealtime(); 7422 plogd("mLastEmergencyCallTime=" + mLastEmergencyCallTime); 7423 } 7424 } 7425 7426 /** 7427 * Check if satellite is in emergency mode. 7428 */ isInEmergencyMode()7429 public boolean isInEmergencyMode() { 7430 synchronized (mLock) { 7431 if (mLastEmergencyCallTime == 0) return false; 7432 7433 long currentTime = getElapsedRealtime(); 7434 if ((currentTime - mLastEmergencyCallTime) <= mSatelliteEmergencyModeDurationMillis) { 7435 plogd("Satellite is in emergency mode"); 7436 return true; 7437 } 7438 return false; 7439 } 7440 } 7441 getSatelliteEmergencyModeDurationFromOverlayConfig(@onNull Context context)7442 private long getSatelliteEmergencyModeDurationFromOverlayConfig(@NonNull Context context) { 7443 Integer duration = DEFAULT_SATELLITE_EMERGENCY_MODE_DURATION_SECONDS; 7444 try { 7445 duration = context.getResources().getInteger(com.android.internal.R.integer 7446 .config_satellite_emergency_mode_duration); 7447 } catch (Resources.NotFoundException ex) { 7448 ploge("getSatelliteEmergencyModeDurationFromOverlayConfig: got ex=" + ex); 7449 } 7450 return TimeUnit.SECONDS.toMillis(duration); 7451 } 7452 getEvaluateEsosProfilesPrioritizationDurationMillis()7453 private long getEvaluateEsosProfilesPrioritizationDurationMillis() { 7454 return TimeUnit.MINUTES.toMillis(1); 7455 } 7456 7457 /** 7458 * Calculate priority 7459 * 1. Active eSOS profiles are higher priority than inactive eSOS profiles. 7460 * 2. Carrier Enabled eSOS profile is higher priority than OEM enabled eSOS profile. 7461 * 3. Among active carrier eSOS profiles user selected(default SMS SIM) eSOS profile will be 7462 * the highest priority. 7463 */ 7464 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) evaluateESOSProfilesPrioritization()7465 protected void evaluateESOSProfilesPrioritization() { 7466 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 7467 plogd("evaluateESOSProfilesPrioritization: Flag CarrierRoamingNbIotNtn is disabled"); 7468 return; 7469 } 7470 7471 if (isSatelliteEnabledOrBeingEnabled()) { 7472 plogd("evaluateESOSProfilesPrioritization: Skip evaluation as satellite is enabled " 7473 + "or being enabled"); 7474 return; 7475 } 7476 7477 boolean isChanged = false; 7478 List<SubscriptionInfo> allSubInfos = mSubscriptionManagerService.getAllSubInfoList( 7479 mContext.getOpPackageName(), mContext.getAttributionTag()); 7480 // Key : priority - lower value has higher priority; Value : List<SubscriptionInfo> 7481 TreeMap<Integer, List<SubscriptionInfo>> newSubsInfoListPerPriority = new TreeMap<>(); 7482 plogd("evaluateESOSProfilesPrioritization: allSubInfos.size()=" + allSubInfos.size()); 7483 synchronized (mSatelliteTokenProvisionedLock) { 7484 for (SubscriptionInfo info : allSubInfos) { 7485 int subId = info.getSubscriptionId(); 7486 boolean isActive = info.isActive(); 7487 boolean isDefaultSmsSubId = 7488 mSubscriptionManagerService.getDefaultSmsSubId() == subId; 7489 boolean isNtnOnly = info.isOnlyNonTerrestrialNetwork(); 7490 boolean isESOSSupported = info.isSatelliteESOSSupported(); 7491 boolean isCarrierSatelliteHigherPriority = 7492 isCarrierSatelliteHigherPriority(info); 7493 if (!isNtnOnly && !isESOSSupported) { 7494 continue; 7495 } 7496 if (!isActive && !isNtnOnly) { 7497 continue; 7498 } 7499 if (!isNtnOnly && !isCarrierConfigLoaded(subId)) { 7500 // Skip to add priority list if the carrier config is not loaded properly 7501 // for the given carrier subscription. 7502 continue; 7503 } 7504 7505 int keyPriority = (isESOSSupported && isActive && isDefaultSmsSubId 7506 && isCarrierSatelliteHigherPriority) 7507 ? 0 : (isESOSSupported && isActive && 7508 isCarrierSatelliteHigherPriority) 7509 ? 1 : (isNtnOnly) 7510 ? 2 : (isESOSSupported) 7511 ? 3 : -1; 7512 if (keyPriority != -1) { 7513 newSubsInfoListPerPriority.computeIfAbsent(keyPriority, 7514 k -> new ArrayList<>()).add(info); 7515 } else { 7516 plogw("evaluateESOSProfilesPrioritization: Got -1 keyPriority for subId=" 7517 + info.getSubscriptionId()); 7518 } 7519 7520 Pair<String, Integer> subscriberIdPair = getSubscriberIdAndType(info); 7521 String newSubscriberId = subscriberIdPair.first; 7522 Optional<String> oldSubscriberId = mSubscriberIdPerSub.entrySet().stream() 7523 .filter(entry -> entry.getValue().equals(subId)) 7524 .map(Map.Entry::getKey).findFirst(); 7525 7526 if (oldSubscriberId.isPresent() 7527 && !newSubscriberId.equals(oldSubscriberId.get())) { 7528 mSubscriberIdPerSub.remove(oldSubscriberId.get()); 7529 mProvisionedSubscriberId.remove(oldSubscriberId.get()); 7530 logd("Old phone number is removed: id = " + subId); 7531 isChanged = true; 7532 } 7533 if (!newSubscriberId.isEmpty()) { 7534 mSubscriberIdPerSub.put(newSubscriberId, subId); 7535 } 7536 } 7537 } 7538 plogd("evaluateESOSProfilesPrioritization: newSubsInfoListPerPriority.size()=" 7539 + newSubsInfoListPerPriority.size()); 7540 7541 if (!mHasSentBroadcast && newSubsInfoListPerPriority.size() == 0) { 7542 logd("evaluateESOSProfilesPrioritization: no satellite subscription available"); 7543 return; 7544 } 7545 7546 // If priority has changed, send broadcast for provisioned ESOS subs IDs 7547 synchronized (mSatelliteTokenProvisionedLock) { 7548 List<SatelliteSubscriberProvisionStatus> newEvaluatedSubscriberProvisionStatus = 7549 getPrioritizedSatelliteSubscriberProvisionStatusList( 7550 newSubsInfoListPerPriority); 7551 if (isPriorityChanged(mSubsInfoListPerPriority, newSubsInfoListPerPriority) 7552 || isSubscriberContentChanged(mLastEvaluatedSubscriberProvisionStatus, 7553 newEvaluatedSubscriberProvisionStatus) 7554 || isChanged) { 7555 mSubsInfoListPerPriority = newSubsInfoListPerPriority; 7556 mLastEvaluatedSubscriberProvisionStatus = newEvaluatedSubscriberProvisionStatus; 7557 sendBroadCastForProvisionedESOSSubs(); 7558 mHasSentBroadcast = true; 7559 selectBindingSatelliteSubscription(false); 7560 } 7561 } 7562 } 7563 7564 // to check if the contents of carrier config is loaded properly isCarrierConfigLoaded(int subId)7565 private Boolean isCarrierConfigLoaded(int subId) { 7566 PersistableBundle carrierConfig = mCarrierConfigManager 7567 .getConfigForSubId(subId, KEY_CARRIER_CONFIG_APPLIED_BOOL); 7568 return carrierConfig != null ? carrierConfig.getBoolean( 7569 CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL) : false; 7570 } 7571 7572 // The subscriberId for ntnOnly SIMs is the Iccid, whereas for ESOS supported SIMs, the 7573 // subscriberId is the Imsi prefix 6 digit + phone number. getSubscriberIdAndType(@ullable SubscriptionInfo info)7574 private Pair<String, Integer> getSubscriberIdAndType(@Nullable SubscriptionInfo info) { 7575 String subscriberId = ""; 7576 @SatelliteSubscriberInfo.SubscriberIdType int subscriberIdType = 7577 SatelliteSubscriberInfo.SUBSCRIBER_ID_TYPE_ICCID; 7578 if (info == null) { 7579 logd("getSubscriberIdAndType: subscription info is null"); 7580 return new Pair<>(subscriberId, subscriberIdType); 7581 } 7582 if (info.isOnlyNonTerrestrialNetwork()) { 7583 subscriberId = info.getIccId(); 7584 } else if (info.isSatelliteESOSSupported()) { 7585 subscriberId = getPhoneNumberBasedCarrier(info.getSubscriptionId()); 7586 subscriberIdType = SatelliteSubscriberInfo.SUBSCRIBER_ID_TYPE_IMSI_MSISDN; 7587 } 7588 logd("getSubscriberIdAndType: subscriberId=" 7589 + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, subscriberId) 7590 + ", subscriberIdType=" + subscriberIdType); 7591 return new Pair<>(subscriberId, subscriberIdType); 7592 } 7593 7594 /** Get subscriberId from phone number and carrier information. */ 7595 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) getPhoneNumberBasedCarrier(int subId)7596 public String getPhoneNumberBasedCarrier(int subId) { 7597 String subscriberId = ""; 7598 SubscriptionInfoInternal internal = mSubscriptionManagerService.getSubscriptionInfoInternal( 7599 subId); 7600 if (internal == null) { 7601 plogd("getPhoneNumberBasedCarrier: subscriptionInfoInternal is null."); 7602 return subscriberId; 7603 } 7604 7605 SubscriptionManager subscriptionManager = mContext.getSystemService( 7606 SubscriptionManager.class); 7607 if (mInjectSubscriptionManager != null) { 7608 plogd("getPhoneNumberBasedCarrier: InjectSubscriptionManager"); 7609 subscriptionManager = mInjectSubscriptionManager; 7610 } 7611 7612 if (subscriptionManager == null) { 7613 plogd("getPhoneNumberBasedCarrier: subscriptionManager is null"); 7614 return subscriberId; 7615 } 7616 7617 String phoneNumber = subscriptionManager.getPhoneNumber(subId); 7618 if (TextUtils.isEmpty(phoneNumber)) { 7619 plogd("getPhoneNumberBasedCarrier: phoneNumber is empty."); 7620 return subscriberId; 7621 } 7622 7623 String imsi = internal.getImsi(); 7624 if (TextUtils.isEmpty(imsi)) { 7625 plogd("getPhoneNumberBasedCarrier: imsi is empty"); 7626 return subscriberId; 7627 } 7628 7629 if (imsi.length() < 6) { 7630 plogd("getPhoneNumberBasedCarrier: imsi length is less than 6"); 7631 return subscriberId; 7632 } 7633 7634 subscriberId = internal.getImsi().substring(0, 6) 7635 + phoneNumber.replaceFirst("^\\+", ""); 7636 plogd("getPhoneNumberBasedCarrier: subscriberId=" 7637 + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, subscriberId)); 7638 return subscriberId; 7639 } 7640 isPriorityChanged(Map<Integer, List<SubscriptionInfo>> currentMap, Map<Integer, List<SubscriptionInfo>> newMap)7641 private boolean isPriorityChanged(Map<Integer, List<SubscriptionInfo>> currentMap, 7642 Map<Integer, List<SubscriptionInfo>> newMap) { 7643 if (currentMap.size() == 0 || currentMap.size() != newMap.size()) { 7644 return true; 7645 } 7646 7647 for (Map.Entry<Integer, List<SubscriptionInfo>> entry : currentMap.entrySet()) { 7648 List<SubscriptionInfo> currentList = entry.getValue(); 7649 List<SubscriptionInfo> newList = newMap.get(entry.getKey()); 7650 if (newList == null || currentList == null || currentList.size() != newList.size()) { 7651 return true; 7652 } 7653 for (int i = 0; i < currentList.size(); i++) { 7654 if (currentList.get(i).getSubscriptionId() != newList.get(i).getSubscriptionId()) { 7655 logd("isPriorityChanged: cur=" + currentList.get(i) + " , new=" + newList.get( 7656 i)); 7657 return true; 7658 } 7659 } 7660 } 7661 return false; 7662 } 7663 7664 // Checks if there are any changes between subscriberInfos. return false if the same. 7665 // Note that, Use lists with the same priority so we can compare contents properly. isSubscriberContentChanged(List<SatelliteSubscriberProvisionStatus> currentList, List<SatelliteSubscriberProvisionStatus> newList)7666 private boolean isSubscriberContentChanged(List<SatelliteSubscriberProvisionStatus> currentList, 7667 List<SatelliteSubscriberProvisionStatus> newList) { 7668 if (currentList.size() != newList.size()) { 7669 return true; 7670 } 7671 for (int i = 0; i < currentList.size(); i++) { 7672 SatelliteSubscriberProvisionStatus curSub = currentList.get(i); 7673 SatelliteSubscriberProvisionStatus newSub = newList.get(i); 7674 if (!curSub.getSatelliteSubscriberInfo().equals(newSub.getSatelliteSubscriberInfo())) { 7675 logd("isSubscriberContentChanged: cur=" + curSub + " , new=" + newSub); 7676 return true; 7677 } 7678 } 7679 return false; 7680 } 7681 sendBroadCastForProvisionedESOSSubs()7682 private void sendBroadCastForProvisionedESOSSubs() { 7683 String packageName = getConfigSatelliteGatewayServicePackage(); 7684 String className = getConfigSatelliteCarrierRoamingEsosProvisionedClass(); 7685 if (packageName == null || className == null || packageName.isEmpty() 7686 || className.isEmpty()) { 7687 logd("sendBroadCastForProvisionedESOSSubs: packageName or className is null or empty."); 7688 return; 7689 } 7690 String action = SatelliteManager.ACTION_SATELLITE_SUBSCRIBER_ID_LIST_CHANGED; 7691 7692 Intent intent = new Intent(action); 7693 intent.setComponent(new ComponentName(packageName, className)); 7694 if (mFeatureFlags.hsumBroadcast()) { 7695 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 7696 } else { 7697 mContext.sendBroadcast(intent); 7698 } 7699 logd("sendBroadCastForProvisionedESOSSubs" + intent); 7700 } 7701 7702 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) getStringFromOverlayConfig(int resourceId)7703 protected String getStringFromOverlayConfig(int resourceId) { 7704 String name; 7705 try { 7706 name = mContext.getResources().getString(resourceId); 7707 } catch (Resources.NotFoundException ex) { 7708 loge("getStringFromOverlayConfig: ex=" + ex); 7709 name = null; 7710 } 7711 return name; 7712 } 7713 7714 /** 7715 * Request to get the name to display for Satellite. 7716 * 7717 * @param result The result receiver that returns the name to display for the satellite 7718 * or an error code if the request failed. 7719 */ requestSatelliteDisplayName(@onNull ResultReceiver result)7720 public void requestSatelliteDisplayName(@NonNull ResultReceiver result) { 7721 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 7722 plogd("requestSatelliteDisplayName: carrierRoamingNbIotNtn flag is disabled"); 7723 result.send(SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED, null); 7724 return; 7725 } 7726 7727 int subId = getSelectedSatelliteSubId(); 7728 String displayName = getConfigForSubId(subId).getString( 7729 KEY_SATELLITE_DISPLAY_NAME_STRING, "Satellite"); 7730 7731 plogd("requestSatelliteDisplayName: " + displayName); 7732 Bundle bundle = new Bundle(); 7733 bundle.putString(SatelliteManager.KEY_SATELLITE_DISPLAY_NAME, displayName); 7734 result.send(SATELLITE_RESULT_SUCCESS, bundle); 7735 } 7736 7737 /** 7738 * Request to get list of prioritized satellite tokens to be used for provision. 7739 * 7740 * @param result The result receiver, which returns the list of prioritized satellite tokens 7741 * to be used for provision if the request is successful or an error code if the request failed. 7742 */ requestSatelliteSubscriberProvisionStatus(@onNull ResultReceiver result)7743 public void requestSatelliteSubscriberProvisionStatus(@NonNull ResultReceiver result) { 7744 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 7745 logd("requestSatelliteSubscriberProvisionStatus: carrierRoamingNbIotNtn is disabled"); 7746 result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null); 7747 return; 7748 } 7749 List<SatelliteSubscriberProvisionStatus> list = 7750 getPrioritizedSatelliteSubscriberProvisionStatusList(); 7751 logd("requestSatelliteSubscriberProvisionStatus: " + list); 7752 final Bundle bundle = new Bundle(); 7753 bundle.putParcelableList(SatelliteManager.KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN, list); 7754 result.send(SATELLITE_RESULT_SUCCESS, bundle); 7755 } 7756 7757 private List<SatelliteSubscriberProvisionStatus> getPrioritizedSatelliteSubscriberProvisionStatusList()7758 getPrioritizedSatelliteSubscriberProvisionStatusList() { 7759 synchronized (mSatelliteTokenProvisionedLock) { 7760 return getPrioritizedSatelliteSubscriberProvisionStatusList(mSubsInfoListPerPriority); 7761 } 7762 } 7763 7764 private List<SatelliteSubscriberProvisionStatus> getPrioritizedSatelliteSubscriberProvisionStatusList( Map<Integer, List<SubscriptionInfo>> subsInfoListPerPriority)7765 getPrioritizedSatelliteSubscriberProvisionStatusList( 7766 Map<Integer, List<SubscriptionInfo>> subsInfoListPerPriority) { 7767 List<SatelliteSubscriberProvisionStatus> list = new ArrayList<>(); 7768 synchronized (mSatelliteTokenProvisionedLock) { 7769 for (int priority : subsInfoListPerPriority.keySet()) { 7770 List<SubscriptionInfo> infoList = subsInfoListPerPriority.get(priority); 7771 if (infoList == null) { 7772 logd("getPrioritySatelliteSubscriberProvisionStatusList: no exist this " 7773 + "priority " + priority); 7774 continue; 7775 } 7776 for (SubscriptionInfo info : infoList) { 7777 Pair<String, Integer> subscriberIdPair = getSubscriberIdAndType(info); 7778 String subscriberId = subscriberIdPair.first; 7779 int carrierId = info.getCarrierId(); 7780 String apn = getConfigForSubId(info.getSubscriptionId()) 7781 .getString(KEY_SATELLITE_NIDD_APN_NAME_STRING, ""); 7782 logd("getPrioritySatelliteSubscriberProvisionStatusList:" 7783 + " subscriberId:" 7784 + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, subscriberId) 7785 + " , carrierId=" + carrierId + " , apn=" + apn); 7786 if (subscriberId.isEmpty()) { 7787 logd("getPrioritySatelliteSubscriberProvisionStatusList: getSubscriberId " 7788 + "failed skip this subscriberId."); 7789 continue; 7790 } 7791 SatelliteSubscriberInfo satelliteSubscriberInfo = 7792 new SatelliteSubscriberInfo.Builder().setSubscriberId(subscriberId) 7793 .setCarrierId(carrierId).setNiddApn(apn) 7794 .setSubscriptionId(info.getSubscriptionId()) 7795 .setSubscriberIdType(subscriberIdPair.second) 7796 .build(); 7797 boolean provisioned = mProvisionedSubscriberId.getOrDefault(subscriberId, 7798 false); 7799 logd("getPrioritySatelliteSubscriberProvisionStatusList: " 7800 + "satelliteSubscriberInfo=" + satelliteSubscriberInfo 7801 + ", provisioned=" + provisioned); 7802 list.add(new SatelliteSubscriberProvisionStatus.Builder() 7803 .setSatelliteSubscriberInfo(satelliteSubscriberInfo) 7804 .setProvisioned(provisioned).build()); 7805 mSubscriberIdPerSub.put(subscriberId, info.getSubscriptionId()); 7806 } 7807 } 7808 } 7809 return list; 7810 } 7811 getSelectedSatelliteSubId()7812 public int getSelectedSatelliteSubId() { 7813 plogd("getSelectedSatelliteSubId: subId=" + mSelectedSatelliteSubId); 7814 return mSelectedSatelliteSubId; 7815 } 7816 7817 /** 7818 * Request to get the currently selected satellite subscription id. 7819 * 7820 * @param result The result receiver that returns the currently selected satellite subscription 7821 * id if the request is successful or an error code if the request failed. 7822 */ requestSelectedNbIotSatelliteSubscriptionId(@onNull ResultReceiver result)7823 public void requestSelectedNbIotSatelliteSubscriptionId(@NonNull ResultReceiver result) { 7824 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 7825 result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null); 7826 logd("requestSelectedNbIotSatelliteSubscriptionId: carrierRoamingNbIotNtn is disabled"); 7827 return; 7828 } 7829 7830 int selectedSatelliteSubId = getSelectedSatelliteSubId(); 7831 plogd("requestSelectedNbIotSatelliteSubscriptionId: " + selectedSatelliteSubId); 7832 if (selectedSatelliteSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 7833 result.send(SATELLITE_RESULT_NO_VALID_SATELLITE_SUBSCRIPTION, null); 7834 logd("requestSelectedNbIotSatelliteSubscriptionId: " 7835 + "selectedSatelliteSubId is invalid"); 7836 return; 7837 } 7838 7839 Bundle bundle = new Bundle(); 7840 bundle.putInt(SatelliteManager.KEY_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_ID, 7841 selectedSatelliteSubId); 7842 result.send(SATELLITE_RESULT_SUCCESS, bundle); 7843 } 7844 selectBindingSatelliteSubscription(boolean shouldIgnoreEnabledState)7845 private void selectBindingSatelliteSubscription(boolean shouldIgnoreEnabledState) { 7846 if ((isSatelliteEnabled() || isSatelliteBeingEnabled()) && !shouldIgnoreEnabledState) { 7847 plogd("selectBindingSatelliteSubscription: satellite subscription will be selected " 7848 + "once the satellite session ends"); 7849 return; 7850 } 7851 7852 int selectedSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 7853 List<SatelliteSubscriberProvisionStatus> satelliteSubscribers = 7854 getPrioritizedSatelliteSubscriberProvisionStatusList(); 7855 7856 for (SatelliteSubscriberProvisionStatus status : satelliteSubscribers) { 7857 int subId = getSubIdFromSubscriberId( 7858 status.getSatelliteSubscriberInfo().getSubscriberId()); 7859 7860 if (status.isProvisioned() && isActiveSubId(subId) && 7861 isSatelliteAvailableAtCurrentLocation( 7862 mSubscriptionManagerService.getSubscriptionInfo(subId))) { 7863 selectedSubId = subId; 7864 break; 7865 } 7866 } 7867 7868 if (selectedSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID 7869 && isSatelliteSupportedViaOem()) { 7870 selectedSubId = getNtnOnlySubscriptionId(); 7871 } 7872 7873 int preSelectedSatelliteSubId = getSelectedSatelliteSubId(); 7874 setSelectedSatelliteSubId(selectedSubId); 7875 if (preSelectedSatelliteSubId != getSelectedSatelliteSubId()) { 7876 plogd("selectBindingSatelliteSubscription: SelectedSatelliteSubId changed"); 7877 mSatelliteSubIdChangedRegistrants.notifyRegistrants(); 7878 handleEventSelectedNbIotSatelliteSubscriptionChanged(selectedSubId); 7879 handleCarrierRoamingNtnAvailableServicesChanged(); 7880 evaluateCarrierRoamingNtnEligibilityChange(); 7881 } 7882 7883 setSatellitePhone(selectedSubId); 7884 if (selectedSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 7885 int carrierId = getSatelliteCarrierId(); 7886 if (carrierId != UNKNOWN_CARRIER_ID) { 7887 mControllerMetricsStats.setCarrierId(carrierId); 7888 } else { 7889 logd("selectBindingSatelliteSubscription: Carrier ID is UNKNOWN_CARRIER_ID"); 7890 } 7891 mControllerMetricsStats.setIsNtnOnlyCarrier(isNtnOnlyCarrier()); 7892 } 7893 plogd("selectBindingSatelliteSubscription: SelectedSatelliteSubId=" + selectedSubId); 7894 } 7895 7896 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) isCarrierSatelliteHigherPriority(SubscriptionInfo info)7897 protected boolean isCarrierSatelliteHigherPriority(SubscriptionInfo info) { 7898 if(!isSatelliteAccessAllowedAtCurrentLocation()) { 7899 return true; 7900 } 7901 if(isSatelliteAvailableAtCurrentLocation(info)) { 7902 return true; 7903 } 7904 return false; 7905 } 7906 7907 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) isSatelliteAvailableAtCurrentLocation(@ullable SubscriptionInfo info)7908 protected boolean isSatelliteAvailableAtCurrentLocation(@Nullable SubscriptionInfo info) { 7909 if(info == null) { 7910 plogd("isSatelliteAvailableAtCurrentLocation: subscriptionInfo is null"); 7911 return false; 7912 } 7913 if (mCtsSatelliteAccessAllowedSubIds.contains(info.getSubscriptionId())) { 7914 plogd("isSatelliteAvailableAtCurrentLocation: subscriptionId=" 7915 + info.getSubscriptionId() + " is allowed for CTS testing"); 7916 return true; 7917 } 7918 if (!isSatelliteAccessAllowedAtCurrentLocation()) { 7919 plogd("isSatelliteAvailableAtCurrentLocation: satellite access is not allowed at " + 7920 "current location"); 7921 return false; 7922 } 7923 if(info.isOnlyNonTerrestrialNetwork()) { 7924 return true; 7925 } 7926 7927 int[] carrierTagIdsArray = mContext.getResources().getIntArray( 7928 R.array.config_verizon_satellite_enabled_tagids); 7929 List<Integer> carrierTagIds = null; 7930 7931 if(carrierTagIdsArray != null && carrierTagIdsArray.length > 0) { 7932 carrierTagIds = Arrays.stream(carrierTagIdsArray) 7933 .boxed() 7934 .collect(Collectors.toList()); 7935 } 7936 7937 if(carrierTagIds == null) { 7938 String satelliteAccessConfigFile = 7939 getSatelliteAccessConfigurationFileFromOverlayConfig(); 7940 if (TextUtils.isEmpty(satelliteAccessConfigFile)) { 7941 plogd("isSatelliteAvailableAtCurrentLocation: device does not support" 7942 + " custom satellite access configuration per location"); 7943 return true; 7944 } else { 7945 plogd("isSatelliteAvailableAtCurrentLocation: tagids for carrier " 7946 + info.getCarrierName() + ", subId=" + info.getSubscriptionId() 7947 + " are not available"); 7948 return false; 7949 } 7950 } 7951 7952 return isCarrierSatelliteAvailableAtCurrentLocation(carrierTagIds); 7953 } 7954 7955 @Nullable getSatelliteAccessConfigurationFileFromOverlayConfig()7956 private String getSatelliteAccessConfigurationFileFromOverlayConfig() { 7957 String satelliteAccessConfigFile = null; 7958 try { 7959 satelliteAccessConfigFile = mContext.getResources().getString( 7960 com.android.internal.R.string.satellite_access_config_file); 7961 } catch (Resources.NotFoundException ex) { 7962 loge("getSatelliteAccessConfigurationFileFromOverlayConfig: got ex=" + ex); 7963 } 7964 7965 logd("satelliteAccessConfigFile =" + satelliteAccessConfigFile); 7966 return satelliteAccessConfigFile; 7967 } 7968 7969 /** 7970 * Compares tagIds and determine if 7971 * carrier satellite is available at current location while selecting highest priority profile. 7972 * 7973 * @param carrierTagIds a list of integer tagIds representing regions where carrier satellite 7974 * coverage is available. 7975 * @return {@code true} if the carrier satellite is available at current location, 7976 * {@code false} otherwise. 7977 */ isCarrierSatelliteAvailableAtCurrentLocation( List<Integer> carrierTagIds)7978 public boolean isCarrierSatelliteAvailableAtCurrentLocation( 7979 List<Integer> carrierTagIds) { 7980 synchronized (mSatelliteAccessConfigLock) { 7981 return !Collections.disjoint(carrierTagIds, mCurrentLocationTagIds); 7982 } 7983 } 7984 getSubIdFromSubscriberId(String subscriberId)7985 private int getSubIdFromSubscriberId(String subscriberId) { 7986 synchronized (mSatelliteTokenProvisionedLock) { 7987 return mSubscriberIdPerSub.getOrDefault(subscriberId, 7988 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 7989 } 7990 } 7991 isActiveSubId(int subId)7992 private boolean isActiveSubId(int subId) { 7993 SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(subId); 7994 if (subInfo == null) { 7995 logd("isActiveSubId: subscription associated with subId=" + subId + " not found"); 7996 return false; 7997 } 7998 return subInfo.isActive(); 7999 } 8000 8001 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) isSubscriptionProvisioned(int subId)8002 protected boolean isSubscriptionProvisioned(int subId) { 8003 plogd("isSubscriptionProvisioned: subId=" + subId); 8004 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 8005 plogd("isSubscriptionProvisioned: carrierRoamingNbIotNtn flag is disabled"); 8006 return false; 8007 } 8008 8009 String subscriberId = getSubscriberIdAndType( 8010 mSubscriptionManagerService.getSubscriptionInfo(subId)).first; 8011 if (subscriberId.isEmpty()) { 8012 plogd("isSubscriptionProvisioned: subId=" + subId + " subscriberId is empty."); 8013 return false; 8014 } 8015 8016 synchronized (mSatelliteTokenProvisionedLock) { 8017 return mProvisionedSubscriberId.getOrDefault(subscriberId, false); 8018 } 8019 } 8020 8021 /** 8022 * Deliver the list of provisioned satellite subscriber ids. 8023 * 8024 * @param list List of provisioned satellite subscriber ids. 8025 * @param result The result receiver that returns whether deliver success or fail. 8026 */ provisionSatellite(@onNull List<SatelliteSubscriberInfo> list, @NonNull ResultReceiver result)8027 public void provisionSatellite(@NonNull List<SatelliteSubscriberInfo> list, 8028 @NonNull ResultReceiver result) { 8029 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 8030 result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null); 8031 logd("provisionSatellite: carrierRoamingNbIotNtn not support"); 8032 return; 8033 } 8034 if (list.isEmpty()) { 8035 result.send(SATELLITE_RESULT_INVALID_ARGUMENTS, null); 8036 logd("provisionSatellite: SatelliteSubscriberInfo list is empty"); 8037 return; 8038 } 8039 8040 logd("provisionSatellite:" + list); 8041 RequestProvisionSatelliteArgument request = new RequestProvisionSatelliteArgument(list, 8042 result, true); 8043 sendRequestAsync(CMD_UPDATE_PROVISION_SATELLITE_TOKEN, request, null); 8044 incrementResultReceiverCount("SC:provisionSatellite"); 8045 } 8046 8047 /** 8048 * Request to update system selection channels. 8049 * 8050 * @param result The result receiver that returns if the request is successful or 8051 * an error code if the request failed. 8052 */ updateSystemSelectionChannels( @onNull List<SystemSelectionSpecifier> selectionSpecifiers, @NonNull ResultReceiver result)8053 public void updateSystemSelectionChannels( 8054 @NonNull List<SystemSelectionSpecifier> selectionSpecifiers, 8055 @NonNull ResultReceiver result) { 8056 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 8057 plogd("updateSystemSelectionChannels: " 8058 + "carrierRoamingNbIotNtn flag is disabled"); 8059 result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null); 8060 return; 8061 } 8062 8063 sendRequestAsync(CMD_UPDATE_SYSTEM_SELECTION_CHANNELS, 8064 new UpdateSystemSelectionChannelsArgument(selectionSpecifiers, result), null); 8065 } 8066 8067 /** 8068 * @param subId Subscription ID. 8069 * @return The The map of earfcns with key: regional satellite config Id, 8070 * value: set of earfcns in the corresponding regions associated with the {@code subId}. 8071 */ 8072 @NonNull getRegionalSatelliteEarfcns(int subId)8073 public Map<String, Set<Integer>> getRegionalSatelliteEarfcns(int subId) { 8074 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 8075 logd("getRegionalSatelliteEarfcns: carrierRoamingNbIotNtnFlag is disabled"); 8076 return new HashMap<>(); 8077 } 8078 synchronized (mRegionalSatelliteEarfcnsLock) { 8079 if (mRegionalSatelliteEarfcns.containsKey(subId)) { 8080 return mRegionalSatelliteEarfcns.get(subId); 8081 } else { 8082 logd("getRegionalSatelliteEarfcns: Earfcns for subId: " + subId + " not found"); 8083 return new HashMap<>(); 8084 } 8085 } 8086 } 8087 8088 /** 8089 * Update regional satellite earfcn information from carrier config. 8090 */ updateRegionalSatelliteEarfcns(int subId)8091 public void updateRegionalSatelliteEarfcns(int subId) { 8092 plogd("updateRegionalSatelliteEarfcns with subId " + subId); 8093 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 8094 plogd("updateRegionalSatelliteEarfcns: " 8095 + "carrierRoamingNbIotNtn flag is disabled"); 8096 return; 8097 } 8098 8099 synchronized (mRegionalSatelliteEarfcnsLock) { 8100 mRegionalSatelliteEarfcns.put(subId, 8101 readRegionalSatelliteEarfcnsFromCarrierConfig(subId)); 8102 } 8103 } 8104 8105 /** 8106 * Deliver the list of deprovisioned satellite subscriber ids. 8107 * 8108 * @param list List of deprovisioned satellite subscriber ids. 8109 * @param result The result receiver that returns whether deliver success or fail. 8110 */ deprovisionSatellite(@onNull List<SatelliteSubscriberInfo> list, @NonNull ResultReceiver result)8111 public void deprovisionSatellite(@NonNull List<SatelliteSubscriberInfo> list, 8112 @NonNull ResultReceiver result) { 8113 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 8114 result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null); 8115 logd("deprovisionSatellite: carrierRoamingNbIotNtn not support"); 8116 return; 8117 } 8118 if (list.isEmpty()) { 8119 result.send(SATELLITE_RESULT_INVALID_ARGUMENTS, null); 8120 logd("deprovisionSatellite: SatelliteSubscriberInfo list is empty"); 8121 return; 8122 } 8123 8124 logd("deprovisionSatellite:" + list); 8125 RequestProvisionSatelliteArgument request = new RequestProvisionSatelliteArgument(list, 8126 result, false); 8127 sendRequestAsync(CMD_UPDATE_PROVISION_SATELLITE_TOKEN, request, null); 8128 incrementResultReceiverCount("SC:provisionSatellite"); 8129 } 8130 8131 /** 8132 * Inform whether application supports NTN SMS in satellite mode. 8133 * 8134 * This method is used by default messaging application to inform framework whether it supports 8135 * NTN SMS or not. 8136 * 8137 * @param ntnSmsSupported {@code true} If application supports NTN SMS, else {@code false}. 8138 */ setNtnSmsSupportedByMessagesApp(boolean ntnSmsSupported)8139 public void setNtnSmsSupportedByMessagesApp(boolean ntnSmsSupported) { 8140 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 8141 return; 8142 } 8143 persistNtnSmsSupportedByMessagesApp(ntnSmsSupported); 8144 handleCarrierRoamingNtnAvailableServicesChanged(); 8145 } 8146 persistNtnSmsSupportedByMessagesApp(boolean ntnSmsSupported)8147 private void persistNtnSmsSupportedByMessagesApp(boolean ntnSmsSupported) { 8148 plogd("persistNtnSmsSupportedByMessagesApp: ntnSmsSupported=" + ntnSmsSupported); 8149 if (!loadSatelliteSharedPreferences()) return; 8150 8151 if (mSharedPreferences == null) { 8152 ploge("persistNtnSmsSupportedByMessagesApp: mSharedPreferences is null"); 8153 } else { 8154 mSharedPreferences.edit().putBoolean( 8155 NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY, ntnSmsSupported).apply(); 8156 synchronized (mNtnSmsSupportedByMessagesAppLock) { 8157 mNtnSmsSupportedByMessagesApp = ntnSmsSupported; 8158 } 8159 } 8160 } 8161 isNtnSmsSupportedByMessagesApp()8162 private boolean isNtnSmsSupportedByMessagesApp() { 8163 synchronized (mNtnSmsSupportedByMessagesAppLock) { 8164 if (mNtnSmsSupportedByMessagesApp != null) { 8165 plogd("isNtnSmsSupportedByMessagesApp:" + mNtnSmsSupportedByMessagesApp); 8166 return mNtnSmsSupportedByMessagesApp; 8167 } 8168 } 8169 8170 if (!loadSatelliteSharedPreferences()) return false; 8171 8172 if (mSharedPreferences == null) { 8173 ploge("isNtnSmsSupportedByMessagesApp: mSharedPreferences is null"); 8174 return false; 8175 } else { 8176 boolean ntnSmsSupported = mSharedPreferences.getBoolean( 8177 NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY, false); 8178 synchronized (mNtnSmsSupportedByMessagesAppLock) { 8179 mNtnSmsSupportedByMessagesApp = ntnSmsSupported; 8180 plogd("isNtnSmsSupportedByMessagesApp:" + mNtnSmsSupportedByMessagesApp); 8181 } 8182 return ntnSmsSupported; 8183 } 8184 } 8185 8186 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) setSatellitePhone(int subId)8187 protected void setSatellitePhone(int subId) { 8188 synchronized (mSatellitePhoneLock) { 8189 mSatellitePhone = SatelliteServiceUtils.getPhone(subId); 8190 plogd("mSatellitePhone: phoneId=" + (mSatellitePhone != null 8191 ? mSatellitePhone.getPhoneId() : "null") + ", subId=" + subId); 8192 } 8193 } 8194 8195 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) setSelectedSatelliteSubId(int subId)8196 protected void setSelectedSatelliteSubId(int subId) { 8197 synchronized (mSatelliteTokenProvisionedLock) { 8198 plogd("setSelectedSatelliteSubId: subId=" + subId); 8199 mSelectedSatelliteSubId = subId; 8200 } 8201 } 8202 8203 /** Return the carrier ID of the binding satellite subscription. */ getSatelliteCarrierId()8204 public int getSatelliteCarrierId() { 8205 SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo( 8206 mSelectedSatelliteSubId); 8207 if (subInfo == null) { 8208 logd("getSatelliteCarrierId: returns UNKNOWN_CARRIER_ID"); 8209 return UNKNOWN_CARRIER_ID; 8210 } 8211 return subInfo.getCarrierId(); 8212 } 8213 8214 /** 8215 * Get whether phone is eligible to connect to carrier roaming non-terrestrial network. 8216 * 8217 * @param phone phone object 8218 * return {@code true} when the subscription is eligible for satellite 8219 * communication if all the following conditions are met: 8220 * <ul> 8221 * <li>Subscription supports P2P satellite messaging which is defined by 8222 * {@link CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} </li> 8223 * <li>{@link CarrierConfigManager#KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT} set to 8224 * {@link CarrierConfigManager#CARRIER_ROAMING_NTN_CONNECT_MANUAL} </li> 8225 * <li>The device is in {@link ServiceState#STATE_OUT_OF_SERVICE}, not connected to Wi-Fi. </li> 8226 * </ul> 8227 */ 8228 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) isCarrierRoamingNtnEligible(@ullable Phone phone)8229 public boolean isCarrierRoamingNtnEligible(@Nullable Phone phone) { 8230 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 8231 plogd("isCarrierRoamingNtnEligible: carrierRoamingNbIotNtn flag is disabled"); 8232 return false; 8233 } 8234 8235 if (!mIsRadioOn) { 8236 plogd("isCarrierRoamingNtnEligible: radio is off"); 8237 return false; 8238 } 8239 8240 boolean isSatelliteAccessAllowed = isSatelliteAccessAllowedAtCurrentLocation(); 8241 if (!isSatelliteAccessAllowed) { 8242 plogd("isCarrierRoamingNtnEligible: satellite access is not allowed"); 8243 return false; 8244 } 8245 8246 // Even if Location service is off, isSatelliteAccessAllowed can be true 8247 // when the device is in emergency call and the allowed cache is valid. 8248 if (!isLocationServiceEnabled()) { 8249 plogd("isCarrierRoamingNtnEligible: Location service is off"); 8250 return false; 8251 } 8252 8253 if (phone == null) { 8254 plogd("isCarrierRoamingNtnEligible: phone is null"); 8255 return false; 8256 } 8257 8258 int subId = getSelectedSatelliteSubId(); 8259 if (!isSatelliteRoamingP2pSmSSupported(subId)) { 8260 plogd("isCarrierRoamingNtnEligible(" + subId + "): doesn't support P2P SMS"); 8261 return false; 8262 } 8263 8264 if (!isSatelliteSupportedViaCarrier(subId)) { 8265 plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() 8266 + "]: satellite is not supported via carrier"); 8267 return false; 8268 } 8269 8270 if (!isSubscriptionProvisioned(subId)) { 8271 plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() 8272 + "]: subscription is not provisioned to use satellite."); 8273 return false; 8274 } 8275 8276 int[] services = getSupportedServicesOnCarrierRoamingNtn(subId); 8277 if (!ArrayUtils.contains(services, NetworkRegistrationInfo.SERVICE_TYPE_SMS)) { 8278 plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() 8279 + "]: SMS is not supported by carrier"); 8280 return false; 8281 } 8282 8283 int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId); 8284 if (carrierRoamingNtnConnectType != CARRIER_ROAMING_NTN_CONNECT_MANUAL) { 8285 plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() + "]: not manual " 8286 + "connect. carrierRoamingNtnConnectType = " + carrierRoamingNtnConnectType); 8287 return false; 8288 } 8289 8290 if (mOverrideNtnEligibility != null) { 8291 // TODO need to send the value from `mOverrideNtnEligibility` or simply true ? 8292 return true; 8293 } 8294 8295 if (SatelliteServiceUtils.isCellularAvailable()) { 8296 plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() 8297 + "]: cellular is available"); 8298 return false; 8299 } 8300 8301 synchronized (mIsWifiConnectedLock) { 8302 if (mIsWifiConnected) { 8303 plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() 8304 + "]: Wi-Fi is connected"); 8305 return false; 8306 } 8307 } 8308 8309 return true; 8310 } 8311 8312 8313 /** 8314 * Checks if the satellite service is supported by the carrier for the specified 8315 * subscription ID and servicetype. 8316 * 8317 * @param subId The subscription id. 8318 * @param serviceType The type of service to check 8319 */ isSatelliteServiceSupportedByCarrier(int subId, @NetworkRegistrationInfo.ServiceType int serviceType)8320 public boolean isSatelliteServiceSupportedByCarrier(int subId, 8321 @NetworkRegistrationInfo.ServiceType int serviceType) { 8322 List<String> satellitePlmnList = getSatellitePlmnsForCarrier(subId); 8323 for (String satellitePlmn : satellitePlmnList) { 8324 if (getSupportedSatelliteServicesForPlmn(subId, satellitePlmn).contains(serviceType)) { 8325 return true; 8326 } 8327 } 8328 return false; 8329 } 8330 8331 /** return satellite phone */ 8332 @Nullable getSatellitePhone()8333 public Phone getSatellitePhone() { 8334 synchronized (mSatellitePhoneLock) { 8335 return mSatellitePhone; 8336 } 8337 } 8338 8339 /** Start PointingUI if it is required. */ startPointingUI()8340 public void startPointingUI() { 8341 synchronized (mNeedsSatellitePointingLock) { 8342 plogd("startPointingUI: mNeedsSatellitePointing=" + mNeedsSatellitePointing 8343 + ", mIsDemoModeEnabled=" + mIsDemoModeEnabled 8344 + ", mIsEmergency=" + mIsEmergency); 8345 if (mNeedsSatellitePointing) { 8346 mPointingAppController.startPointingUI(false /*needFullScreenPointingUI*/, 8347 mIsDemoModeEnabled, mIsEmergency); 8348 } 8349 } 8350 } 8351 8352 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) registerForSatelliteCommunicationAccessStateChanged()8353 protected void registerForSatelliteCommunicationAccessStateChanged() { 8354 if (mRegisteredForSatelliteCommunicationAccessStateChanged.get()) { 8355 if (DEBUG) { 8356 plogd("registerForSatelliteCommunicationAccessStateChanged: already registered."); 8357 } 8358 return; 8359 } 8360 8361 SatelliteManager satelliteManager = mContext.getSystemService(SatelliteManager.class); 8362 if (satelliteManager == null) { 8363 ploge("registerForSatelliteCommunicationAccessStateChanged: SatelliteManager is null"); 8364 return; 8365 } 8366 8367 SatelliteCommunicationAccessStateCallback accessStateCallback = 8368 new SatelliteCommunicationAccessStateCallback() { 8369 @Override 8370 public void onAccessAllowedStateChanged(boolean isAllowed) { 8371 plogd("onAccessStateChanged: isAllowed=" + isAllowed); 8372 if (mFeatureFlags.satelliteExitP2pSessionOutsideGeofence()) { 8373 handleSatelliteAccessAllowedStateChanged(isAllowed); 8374 } else{ 8375 synchronized (mSatelliteAccessConfigLock) { 8376 mSatelliteAccessAllowed = isAllowed; 8377 } 8378 evaluateESOSProfilesPrioritization(); 8379 evaluateCarrierRoamingNtnEligibilityChange(); 8380 handleCarrierRoamingNtnAvailableServicesChanged(); 8381 } 8382 } 8383 8384 @Override 8385 public void onAccessConfigurationChanged( 8386 SatelliteAccessConfiguration satelliteAccessConfiguration) { 8387 plogd("onAccessConfigurationChanged: satelliteAccessConfiguration=" 8388 + satelliteAccessConfiguration); 8389 handleSatelliteAccessConfigUpdateResult(satelliteAccessConfiguration); 8390 } 8391 }; 8392 try { 8393 satelliteManager.registerForCommunicationAccessStateChanged( 8394 this::post, accessStateCallback); 8395 } catch(RuntimeException e) { 8396 plogd("registerForSatelliteCommunicationAccessStateChanged: " 8397 + "satelliteManager.registerForCommunicationAccessStateChanged() failed, " 8398 + "e=" + e); 8399 return; 8400 } 8401 mRegisteredForSatelliteCommunicationAccessStateChanged.set(true); 8402 } 8403 8404 /** Handle access allowed state changes. */ 8405 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) handleSatelliteAccessAllowedStateChanged(boolean isAllowed)8406 public void handleSatelliteAccessAllowedStateChanged(boolean isAllowed) { 8407 plogd("handleSatelliteAccessAllowedStateChanged: isAllowed=" + isAllowed); 8408 synchronized (mSatelliteAccessConfigLock) { 8409 mSatelliteAccessAllowed = isAllowed; 8410 } 8411 8412 evaluateESOSProfilesPrioritization(); 8413 selectBindingSatelliteSubscription(false); 8414 evaluateCarrierRoamingNtnEligibilityChange(); 8415 handleCarrierRoamingNtnAvailableServicesChanged(); 8416 evaluateDisablingP2pSession(); 8417 } 8418 evaluateDisablingP2pSession()8419 private void evaluateDisablingP2pSession() { 8420 boolean isAllowed = isSatelliteAccessAllowedAtCurrentLocation(); 8421 boolean isSatelliteEnabled = isSatelliteEnabled(); 8422 boolean isEmergency = getRequestIsEmergency(); 8423 8424 plogd("evaluateDisablingP2pSession: isAllowed=" + isAllowed 8425 + " isEmergency=" + isEmergency 8426 + " isSatelliteEnabled:" + isSatelliteEnabled); 8427 if (!isAllowed && isSatelliteEnabled && !isEmergency) { 8428 // Disable P2P session if satellite is not allowed in current location 8429 disableSatelliteSession(isEmergency); 8430 } 8431 } 8432 disableSatelliteSession(boolean isEmergency)8433 private void disableSatelliteSession(boolean isEmergency) { 8434 plogd("disableSatelliteSession: isEmergency=" + isEmergency); 8435 requestSatelliteEnabled(false /* enableSatellite */, 8436 false /* enableDemoMode */, isEmergency, 8437 new IIntegerConsumer.Stub() { 8438 @Override 8439 public void accept(int result) { 8440 plogd("disableSatelliteSession:" 8441 + " requestSatelliteEnabled result=" + result); 8442 } 8443 }); 8444 } 8445 handleSatelliteAccessConfigUpdateResult( SatelliteAccessConfiguration satelliteAccessConfig)8446 private void handleSatelliteAccessConfigUpdateResult( 8447 SatelliteAccessConfiguration satelliteAccessConfig) { 8448 if(satelliteAccessConfig != null) { 8449 synchronized (mSatelliteAccessConfigLock) { 8450 plogd("handleSatelliteAccessConfigUpdateResult:" + " satelliteAccessConfig=" 8451 + satelliteAccessConfig); 8452 List<Integer> tagIds = satelliteAccessConfig.getTagIds(); 8453 if (!mCurrentLocationTagIds.equals(tagIds)) { 8454 mCurrentLocationTagIds = tagIds; 8455 sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION), 8456 mEvaluateEsosProfilesPrioritizationDurationMillis); 8457 } 8458 } 8459 } else { 8460 plogd("handleSatelliteAccessConfigUpdateResult: " 8461 + "satelliteAccessConfiguration is null"); 8462 } 8463 } 8464 handleEventSatelliteRegistrationFailure(int causeCode)8465 private void handleEventSatelliteRegistrationFailure(int causeCode) { 8466 plogd("handleEventSatelliteRegistrationFailure: " + causeCode); 8467 8468 List<ISatelliteModemStateCallback> deadCallersList = new ArrayList<>(); 8469 mSatelliteRegistrationFailureListeners.values().forEach(listener -> { 8470 try { 8471 listener.onRegistrationFailure(causeCode); 8472 } catch (RemoteException e) { 8473 logd("handleEventSatelliteRegistrationFailure RemoteException: " + e); 8474 deadCallersList.add(listener); 8475 } 8476 }); 8477 deadCallersList.forEach(listener -> { 8478 mSatelliteRegistrationFailureListeners.remove(listener.asBinder()); 8479 }); 8480 } 8481 handleEventTerrestrialNetworkAvailableChanged(boolean isAvailable)8482 private void handleEventTerrestrialNetworkAvailableChanged(boolean isAvailable) { 8483 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 8484 plogd("handleEventTerrestrialNetworkAvailableChanged: " 8485 + "carrierRoamingNbIotNtn flag is disabled"); 8486 return; 8487 } 8488 8489 plogd("handleEventTerrestrialNetworkAvailableChanged: " + isAvailable); 8490 8491 List<ISatelliteModemStateCallback> deadCallersList = new ArrayList<>(); 8492 mTerrestrialNetworkAvailableChangedListeners.values().forEach(listener -> { 8493 try { 8494 listener.onTerrestrialNetworkAvailableChanged(isAvailable); 8495 } catch (RemoteException e) { 8496 logd("handleEventTerrestrialNetworkAvailableChanged RemoteException: " + e); 8497 deadCallersList.add(listener); 8498 } 8499 }); 8500 deadCallersList.forEach(listener -> { 8501 mTerrestrialNetworkAvailableChangedListeners.remove(listener.asBinder()); 8502 }); 8503 8504 if (isAvailable && !mIsEmergency) { 8505 requestSatelliteEnabled( 8506 false /* enableSatellite */, false /* enableDemoMode */, 8507 false /* isEmergency */, 8508 new IIntegerConsumer.Stub() { 8509 @Override 8510 public void accept(int result) { 8511 plogd("handleEventTerrestrialNetworkAvailableChanged:" 8512 + " requestSatelliteEnabled result=" + result); 8513 } 8514 }); 8515 } 8516 } 8517 8518 /** 8519 * This API can be used by only CTS to override the cached value for the device overlay config 8520 * value : 8521 * config_satellite_gateway_service_package and 8522 * config_satellite_carrier_roaming_esos_provisioned_class. 8523 * These values are set before sending an intent to broadcast there are any change to list of 8524 * subscriber informations. 8525 * 8526 * @param name the name is one of the following that constitute an intent. 8527 * component package name, or component class name. 8528 * @return {@code true} if the setting is successful, {@code false} otherwise. 8529 */ setSatelliteSubscriberIdListChangedIntentComponent(String name)8530 public boolean setSatelliteSubscriberIdListChangedIntentComponent(String name) { 8531 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 8532 logd("setSatelliteSubscriberIdListChangedIntentComponent: carrierRoamingNbIotNtn is " 8533 + "disabled"); 8534 return false; 8535 } 8536 if (!isMockModemAllowed()) { 8537 logd("setSatelliteSubscriberIdListChangedIntentComponent: mock modem is not allowed"); 8538 return false; 8539 } 8540 logd("setSatelliteSubscriberIdListChangedIntentComponent:" + name); 8541 8542 if (name.contains("/")) { 8543 mChangeIntentComponent = true; 8544 } else { 8545 mChangeIntentComponent = false; 8546 return true; 8547 } 8548 boolean result = true; 8549 String[] cmdPart = name.split("/"); 8550 switch (cmdPart[0]) { 8551 case "-p": { 8552 mConfigSatelliteGatewayServicePackage = cmdPart[1]; 8553 break; 8554 } 8555 case "-c": { 8556 mConfigSatelliteCarrierRoamingEsosProvisionedClass = cmdPart[1]; 8557 break; 8558 } 8559 default: 8560 logd("setSatelliteSubscriberIdListChangedIntentComponent: invalid name " + name); 8561 result = false; 8562 break; 8563 } 8564 return result; 8565 } 8566 8567 /** 8568 * This API can be used by only CTS to override the satellite access allowed state for 8569 * a list of subscription IDs. 8570 * 8571 * @param subIdListStr The string representation of the list of subscription IDs, 8572 * which are numbers separated by comma. 8573 * @return {@code true} if the satellite access allowed state is set successfully, 8574 * {@code false} otherwise. 8575 */ setSatelliteAccessAllowedForSubscriptions(@ullable String subIdListStr)8576 public boolean setSatelliteAccessAllowedForSubscriptions(@Nullable String subIdListStr) { 8577 if (!isMockModemAllowed()) { 8578 plogd("setSatelliteAccessAllowedForSubscriptions: mock modem not allowed"); 8579 return false; 8580 } 8581 8582 plogd("setSatelliteAccessAllowedForSubscriptions: subIdListStr=" + subIdListStr); 8583 if (subIdListStr == null) { 8584 mCtsSatelliteAccessAllowedSubIds.clear(); 8585 return true; 8586 } 8587 8588 List<Integer> subIdList = new ArrayList<>(); 8589 for (String subIdStr : subIdListStr.split(",")) { 8590 try { 8591 subIdList.add(Integer.parseInt(subIdStr)); 8592 } catch (NumberFormatException e) { 8593 plogd("setSatelliteAccessAllowedForSubscriptions: invalid subIdStr=" + subIdStr); 8594 return false; 8595 } 8596 } 8597 mCtsSatelliteAccessAllowedSubIds.clear(); 8598 mCtsSatelliteAccessAllowedSubIds.addAll(subIdList); 8599 selectBindingSatelliteSubscription(false); 8600 return true; 8601 } 8602 8603 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) getConfigSatelliteGatewayServicePackage()8604 protected String getConfigSatelliteGatewayServicePackage() { 8605 if (!mChangeIntentComponent) { 8606 return getStringFromOverlayConfig( 8607 R.string.config_satellite_gateway_service_package); 8608 } 8609 logd("getConfigSatelliteGatewayServicePackage: " + mConfigSatelliteGatewayServicePackage); 8610 return mConfigSatelliteGatewayServicePackage; 8611 } 8612 getConfigSatelliteCarrierRoamingEsosProvisionedClass()8613 private String getConfigSatelliteCarrierRoamingEsosProvisionedClass() { 8614 if (!mChangeIntentComponent) { 8615 return getStringFromOverlayConfig( 8616 R.string.config_satellite_carrier_roaming_esos_provisioned_class); 8617 } 8618 logd("getConfigSatelliteCarrierRoamingEsosProvisionedClass: " 8619 + mConfigSatelliteCarrierRoamingEsosProvisionedClass); 8620 return mConfigSatelliteCarrierRoamingEsosProvisionedClass; 8621 } 8622 registerDefaultSmsSubscriptionChangedBroadcastReceiver()8623 private void registerDefaultSmsSubscriptionChangedBroadcastReceiver() { 8624 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 8625 plogd("registerDefaultSmsSubscriptionChangedBroadcastReceiver: Flag " 8626 + "CarrierRoamingNbIotNtn is disabled"); 8627 return; 8628 } 8629 IntentFilter intentFilter = new IntentFilter(); 8630 intentFilter.addAction(SubscriptionManager.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED); 8631 mContext.registerReceiver(mDefaultSmsSubscriptionChangedBroadcastReceiver, intentFilter); 8632 } 8633 8634 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) getSupportedDeviceStates()8635 protected List<DeviceState> getSupportedDeviceStates() { 8636 return mContext.getSystemService(DeviceStateManager.class).getSupportedDeviceStates(); 8637 } 8638 getFeatureFlags()8639 FeatureFlags getFeatureFlags() { 8640 return mFeatureFlags; 8641 } 8642 isSatelliteDisabled()8643 private boolean isSatelliteDisabled() { 8644 synchronized (mIsSatelliteEnabledLock) { 8645 return ((mIsSatelliteEnabled != null) && !mIsSatelliteEnabled); 8646 } 8647 } 8648 shouldStopWaitForEnableResponseTimer( @onNull RequestSatelliteEnabledArgument argument)8649 private boolean shouldStopWaitForEnableResponseTimer( 8650 @NonNull RequestSatelliteEnabledArgument argument) { 8651 if (argument.enableSatellite) return true; 8652 synchronized (mSatelliteEnabledRequestLock) { 8653 return !mWaitingForSatelliteModemOff; 8654 } 8655 } 8656 8657 /** 8658 * Method to override the Carrier roaming Non-terrestrial network eligibility check 8659 * 8660 * @param state flag to enable or disable the Ntn eligibility check. 8661 * @param resetRequired reset overriding the check with adb command. 8662 */ overrideCarrierRoamingNtnEligibilityChanged(boolean state, boolean resetRequired)8663 public boolean overrideCarrierRoamingNtnEligibilityChanged(boolean state, 8664 boolean resetRequired) { 8665 Log.d(TAG, "overrideCarrierRoamingNtnEligibilityChanged state = " + state 8666 + " resetRequired = " + resetRequired); 8667 if (resetRequired) { 8668 mOverrideNtnEligibility = null; 8669 } else { 8670 if (mOverrideNtnEligibility == null) { 8671 mOverrideNtnEligibility = new AtomicBoolean(state); 8672 } else { 8673 mOverrideNtnEligibility.set(state); 8674 } 8675 synchronized (mSatellitePhoneLock) { 8676 if (this.mSatellitePhone != null) { 8677 updateLastNotifiedNtnEligibilityAndNotify(state); 8678 } 8679 } 8680 } 8681 return true; 8682 } 8683 8684 /** 8685 * This method check for the key KEY_SATELLITE_MAX_DATAGRAM_SIZE in carrier config. If 8686 * available it fetches the value and override the same in SatelliteCapabilities. Otherwise it 8687 * uses the value in the existed mSatelliteCapabilities. 8688 */ overrideSatelliteCapabilitiesIfApplicable()8689 private void overrideSatelliteCapabilitiesIfApplicable() { 8690 int subId = getSelectedSatelliteSubId(); 8691 PersistableBundle config = getPersistableBundle(subId); 8692 if (config.containsKey(KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE_BYTES_INT)) { 8693 int datagramSize = config.getInt(KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE_BYTES_INT); 8694 SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(subId); 8695 if (!(subInfo == null || subInfo.isOnlyNonTerrestrialNetwork())) { 8696 synchronized (mSatelliteCapabilitiesLock) { 8697 this.mSatelliteCapabilities.setMaxBytesPerOutgoingDatagram(datagramSize); 8698 } 8699 } 8700 } 8701 } 8702 8703 /** 8704 * This method returns subscription id for supporting Ntn Only 8705 */ getNtnOnlySubscriptionId()8706 public int getNtnOnlySubscriptionId() { 8707 List<SubscriptionInfo> infoList = mSubscriptionManagerService.getAllSubInfoList( 8708 mContext.getOpPackageName(), mContext.getAttributionTag()); 8709 int subId = infoList.stream() 8710 .filter(info -> info.isOnlyNonTerrestrialNetwork()) 8711 .mapToInt(SubscriptionInfo::getSubscriptionId) 8712 .findFirst() 8713 .orElse(SubscriptionManager.INVALID_SUBSCRIPTION_ID); 8714 logd("getNtnOnlySubscriptionId: subId=" + subId); 8715 return subId; 8716 } 8717 8718 @Nullable getNtnOnlySatelliteSubscriberInfoList( Consumer<Integer> result)8719 private List<SatelliteSubscriberInfo> getNtnOnlySatelliteSubscriberInfoList( 8720 Consumer<Integer> result) { 8721 SatelliteSubscriberInfo satelliteSubscriberInfo = getNtnOnlySatelliteSubscriberInfo(); 8722 if (satelliteSubscriberInfo == null) { 8723 result.accept(SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED); 8724 return null; 8725 } 8726 List<SatelliteSubscriberInfo> satelliteSubscriberInfoList = new ArrayList<>(); 8727 satelliteSubscriberInfoList.add(satelliteSubscriberInfo); 8728 8729 return satelliteSubscriberInfoList; 8730 } 8731 getNtnOnlySatelliteSubscriberInfo()8732 @Nullable private SatelliteSubscriberInfo getNtnOnlySatelliteSubscriberInfo() { 8733 int ntnOnlySubId = getNtnOnlySubscriptionId(); 8734 if (ntnOnlySubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 8735 logw("getNtnOnlySatelliteSubscriberInfo: no ntn only subscription found"); 8736 return null; 8737 } 8738 SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(ntnOnlySubId); 8739 if (subInfo == null) { 8740 logw("getNtnOnlySatelliteSubscriberInfo: no subscription info found for subId=" 8741 + ntnOnlySubId); 8742 return null; 8743 } 8744 return getSatelliteSubscriberInfo(subInfo); 8745 } 8746 getSatelliteSubscriberInfo( @onNull SubscriptionInfo subInfo)8747 @Nullable private SatelliteSubscriberInfo getSatelliteSubscriberInfo( 8748 @NonNull SubscriptionInfo subInfo) { 8749 Pair<String, Integer> subscriberIdPair = getSubscriberIdAndType(subInfo); 8750 String subscriberId = subscriberIdPair.first; 8751 int carrierId = subInfo.getCarrierId(); 8752 String apn = getConfigForSubId(subInfo.getSubscriptionId()) 8753 .getString(KEY_SATELLITE_NIDD_APN_NAME_STRING, ""); 8754 logd("getSatelliteSubscriberInfo: subInfo: " + subInfo 8755 + ", subscriberId:" + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, subscriberId) 8756 + " , carrierId=" + carrierId + " , apn=" + apn); 8757 if (subscriberId.isEmpty()) { 8758 logw("getSatelliteSubscriberInfo: not a satellite subscription."); 8759 return null; 8760 } 8761 return new SatelliteSubscriberInfo.Builder().setSubscriberId(subscriberId) 8762 .setCarrierId(carrierId).setNiddApn(apn) 8763 .setSubscriptionId(subInfo.getSubscriptionId()) 8764 .setSubscriberIdType(subscriberIdPair.second) 8765 .build(); 8766 } 8767 8768 /** 8769 * The method will notify the change in the services update the 8770 * mEntitlementServiceTypeMapPerCarrier. 8771 * 8772 * @param subId : SubscriptionId 8773 * @param plmnServiceTypeMap : entitlement service map. 8774 */ updateAndNotifyChangesInCarrierRoamingNtnAvailableServices(int subId, Map<String, List<Integer>> plmnServiceTypeMap)8775 private void updateAndNotifyChangesInCarrierRoamingNtnAvailableServices(int subId, 8776 Map<String, List<Integer>> plmnServiceTypeMap) { 8777 // If a service list is already cached, check it for changes 8778 int[] existingServices = getSupportedServicesOnCarrierRoamingNtn(subId); 8779 synchronized (mSupportedSatelliteServicesLock) { 8780 mEntitlementServiceTypeMapPerCarrier.put(subId, plmnServiceTypeMap); 8781 } 8782 int[] updatedServices = getSupportedServicesOnCarrierRoamingNtn(subId); 8783 if (existingServices.length > 0 && Arrays.equals(existingServices, updatedServices)) { 8784 plogd("No change in Entitlement service support data"); 8785 return; 8786 } 8787 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 8788 updateLastNotifiedNtnAvailableServicesAndNotify(subId); 8789 evaluateCarrierRoamingNtnEligibilityChange(); 8790 } 8791 } 8792 handleCarrierRoamingNtnAvailableServicesChanged()8793 private void handleCarrierRoamingNtnAvailableServicesChanged() { 8794 int[] activeSubIds = mSubscriptionManagerService.getActiveSubIdList(true); 8795 if (activeSubIds == null) { 8796 plogd("handleCarrierRoamingNtnAvailableServicesChanged: activeSubIds is null."); 8797 return; 8798 } 8799 8800 plogd("handleCarrierRoamingNtnAvailableServicesChanged: activeSubIds size=" 8801 + activeSubIds.length); 8802 for (int subId: activeSubIds) { 8803 handleCarrierRoamingNtnAvailableServicesChanged(subId); 8804 } 8805 } 8806 8807 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) handleCarrierRoamingNtnAvailableServicesChanged(int subId)8808 protected void handleCarrierRoamingNtnAvailableServicesChanged(int subId) { 8809 plogd("handleCarrierRoamingNtnAvailableServicesChanged: subId=" + subId); 8810 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 8811 plogd("handleCarrierRoamingNtnAvailableServicesChanged: " 8812 + "carrierRoamingNbIotNtn flag is disabled"); 8813 return; 8814 } 8815 updateLastNotifiedNtnAvailableServicesAndNotify(subId); 8816 evaluateCarrierRoamingNtnEligibilityChange(); 8817 } 8818 updateLastNotifiedNtnAvailableServicesAndNotify(int subId)8819 private void updateLastNotifiedNtnAvailableServicesAndNotify(int subId) { 8820 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 8821 plogd("notifyNtnAvailableServices: carrierRoamingNbIotNtn flag is disabled"); 8822 return; 8823 } 8824 Phone phone = SatelliteServiceUtils.getPhone(subId); 8825 if (phone == null) { 8826 plogd("notifyNtnAvailableServices: phone is null."); 8827 return; 8828 } 8829 plogd("updateLastNotifiedNtnAvailableServicesAndNotify: phoneId= " + phone.getPhoneId()); 8830 int[] services = getSupportedServicesOnCarrierRoamingNtn(subId); 8831 phone.notifyCarrierRoamingNtnAvailableServicesChanged(services); 8832 } 8833 getAvailableServicesWithEntitlementForSubId(int subId)8834 private int[] getAvailableServicesWithEntitlementForSubId(int subId) { 8835 synchronized (mSupportedSatelliteServicesLock) { 8836 Map<String, List<Integer>> allowedServicesList = 8837 mEntitlementServiceTypeMapPerCarrier.get(subId); 8838 if (allowedServicesList != null && !allowedServicesList.isEmpty()) { 8839 Set<Integer> serviceTypes = new HashSet<>(); 8840 for (List<Integer> values : allowedServicesList.values()) { 8841 serviceTypes.addAll(values); 8842 } 8843 8844 int[] result = new int[serviceTypes.size()]; 8845 int i = 0; 8846 for (int value : serviceTypes) { 8847 result[i++] = value; 8848 } 8849 return result; 8850 } else { 8851 return new int[0]; // Return an empty array if the map is null or empty 8852 } 8853 } 8854 } 8855 8856 /** 8857 * Given a subscription ID, this returns the carriers' supported services on 8858 * non-terrestrial networks. 8859 * 8860 * @param subId Associated subscription ID. 8861 * return supported services at entitlement for the available carriers. Note: If available 8862 * services/allowed service type field is empty at entitlement, information from 8863 * {@link 8864 * CarrierConfigManager#KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY} 8865 * will be returned. 8866 */ getSupportedServicesOnCarrierRoamingNtn(int subId)8867 public int[] getSupportedServicesOnCarrierRoamingNtn(int subId) { 8868 if (isValidSubscriptionId(subId) && isSatelliteSupportedViaCarrier(subId)) { 8869 // check available services supported at entitlement for sub id 8870 int[] services = getAvailableServicesWithEntitlementForSubId(subId); 8871 logd("getAvailableServicesWithEntitlementForSubId: " + Arrays.toString(services)); 8872 if (services.length == 0) { 8873 services = getSupportedSatelliteServicesForCarrier(subId); 8874 } 8875 if (isP2PSmsDisallowedOnCarrierRoamingNtn(subId)) { 8876 services = Arrays.stream(services).filter( 8877 value -> value != NetworkRegistrationInfo.SERVICE_TYPE_SMS).toArray(); 8878 } 8879 return services; 8880 } 8881 return new int[0]; 8882 } 8883 8884 /** 8885 * Whether the P2P SMS over carrier roaming satellite is disallowed or not. 8886 * 8887 * @param subId Associated subscription ID 8888 * return {@code true} when the phone does not support P2P SMS over carrier roaming satellite 8889 * {@code false} otherwise 8890 */ isP2PSmsDisallowedOnCarrierRoamingNtn(int subId)8891 public boolean isP2PSmsDisallowedOnCarrierRoamingNtn(int subId) { 8892 int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId); 8893 if (carrierRoamingNtnConnectType == CARRIER_ROAMING_NTN_CONNECT_MANUAL) { 8894 // Manual Connected 8895 plogd("isP2PSmsDisallowedOnCarrierRoamingNtn: manual connect"); 8896 if (!isNtnSmsSupportedByMessagesApp() 8897 || !isApplicationSupportsP2P(mSatelliteGatewayServicePackageName)) { 8898 plogd("isP2PSmsDisallowedOnCarrierRoamingNtn: APKs do not supports P2P"); 8899 return true; 8900 } 8901 } 8902 plogd("isP2PSmsDisallowedOnCarrierRoamingNtn: P2P is supported"); 8903 return false; 8904 } 8905 8906 @NonNull getSupportedSatelliteServicesForCarrier(int subId)8907 private int[] getSupportedSatelliteServicesForCarrier(int subId) { 8908 PersistableBundle config = getPersistableBundle(subId); 8909 int[] availableServices = config.getIntArray( 8910 KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY); 8911 if (availableServices == null) { 8912 logd("getSupportedSatelliteServicesForCarrier: defaultCapabilities is null"); 8913 return new int[0]; 8914 } 8915 logd("getSupportedSatelliteServicesForCarrier: subId=" + subId 8916 + ", return default values " + Arrays.toString(availableServices)); 8917 return availableServices; 8918 } 8919 8920 /** 8921 * Whether application supports the P2P SMS to connect to carrier roaming non-terrestrial 8922 * network. 8923 * 8924 * @param packageName application's default package name 8925 * return {@code true} when the application supports P2P SMS over the roaming satellite 8926 */ 8927 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) isApplicationSupportsP2P(String packageName)8928 public boolean isApplicationSupportsP2P(String packageName) { 8929 PackageManager pm = mContext.getPackageManager(); 8930 ApplicationInfo applicationInfo = new ApplicationInfo(); 8931 try { 8932 applicationInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA); 8933 } catch (PackageManager.NameNotFoundException e) { 8934 logd("isApplicationSupportsP2P pkgName: " + packageName + " is not installed."); 8935 return false; 8936 } 8937 if (applicationInfo == null || applicationInfo.metaData == null) { 8938 logd("isApplicationSupportsP2P pkgName: " + packageName + " meta-data info is empty."); 8939 return false; 8940 } 8941 return applicationInfo.metaData.getBoolean( 8942 SatelliteManager.METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT); 8943 } 8944 8945 /** 8946 * Registers for the applications state changed. 8947 */ 8948 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) registerApplicationStateChanged()8949 public void registerApplicationStateChanged() { 8950 mDefaultSmsPackageName = Telephony.Sms.getDefaultSmsPackage(mContext); 8951 mSatelliteGatewayServicePackageName = getConfigSatelliteGatewayServicePackage(); 8952 8953 IntentFilter packageFilter = new IntentFilter(); 8954 packageFilter.addAction(Telephony.Sms.Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED); 8955 packageFilter.addAction(Intent.ACTION_PACKAGE_REPLACED); 8956 packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); 8957 packageFilter.addDataScheme("package"); 8958 mContext.registerReceiver(mPackageStateChangedReceiver, packageFilter, 8959 mContext.RECEIVER_EXPORTED); 8960 } 8961 registerLocationServiceStateChanged()8962 private void registerLocationServiceStateChanged() { 8963 IntentFilter intentFilter = new IntentFilter(); 8964 intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION); 8965 mContext.registerReceiver(mLocationServiceStateChangedReceiver, intentFilter); 8966 } 8967 8968 notifyEnabledStateChanged(boolean isEnabled)8969 private void notifyEnabledStateChanged(boolean isEnabled) { 8970 TelephonyRegistryManager trm = mContext.getSystemService(TelephonyRegistryManager.class); 8971 if (trm == null) { 8972 loge("Telephony registry service is down!"); 8973 return; 8974 } 8975 8976 trm.notifySatelliteStateChanged(isEnabled); 8977 logd("notifyEnabledStateChanged to " + isEnabled); 8978 } 8979 getCarrierRoamingNtnSignalStrength(@onNull Phone phone)8980 private NtnSignalStrength getCarrierRoamingNtnSignalStrength(@NonNull Phone phone) { 8981 NtnSignalStrength carrierRoamingNtnSignalStrength = new NtnSignalStrength( 8982 NTN_SIGNAL_STRENGTH_NONE); 8983 8984 if (isInCarrierRoamingNbIotNtn(phone)) { 8985 if (isInConnectedState()) { 8986 synchronized (mNtnSignalsStrengthLock) { 8987 carrierRoamingNtnSignalStrength = mNtnSignalStrength; 8988 } 8989 plogd("getCarrierRoamingNtnSignalStrength[phoneId=" + phone.getPhoneId() 8990 + "]: in carrier roaming nb iot ntn mode."); 8991 } 8992 } else if (isInSatelliteModeForCarrierRoaming(phone)) { 8993 ServiceState serviceState = phone.getServiceState(); 8994 if (serviceState.getState() != ServiceState.STATE_OUT_OF_SERVICE) { 8995 carrierRoamingNtnSignalStrength = new NtnSignalStrength( 8996 phone.getSignalStrength().getLevel()); 8997 plogd("getCarrierRoamingNtnSignalStrength[phoneId=" + phone.getPhoneId() 8998 + "]: is in satellite mode for carrier roaming."); 8999 } 9000 } 9001 9002 return carrierRoamingNtnSignalStrength; 9003 } 9004 9005 /** 9006 * Returns satellite connected state from modem, return true if connected. 9007 */ isInConnectedState()9008 public boolean isInConnectedState() { 9009 synchronized (mSatelliteModemStateLock) { 9010 switch (mSatelliteModemState) { 9011 case SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED: //fallthrough 9012 case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING: //fallthrough 9013 case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING: //fallthrough 9014 case SatelliteManager.SATELLITE_MODEM_STATE_IDLE: 9015 plogd("isInConnectedState: return true"); 9016 return true; 9017 default: 9018 plogd("isInConnectedState: return false"); 9019 return false; 9020 } 9021 } 9022 } 9023 updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify( @ullable Phone phone)9024 protected void updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify( 9025 @Nullable Phone phone) { 9026 if (!mFeatureFlags.carrierRoamingNbIotNtn()) return; 9027 if (phone == null) { 9028 return; 9029 } 9030 9031 NtnSignalStrength currSignalStrength = getCarrierRoamingNtnSignalStrength(phone); 9032 int subId = phone.getSubId(); 9033 synchronized (mSatelliteConnectedLock) { 9034 NtnSignalStrength lastNotifiedSignalStrength = 9035 mLastNotifiedCarrierRoamingNtnSignalStrength.get(subId); 9036 if (lastNotifiedSignalStrength == null 9037 || lastNotifiedSignalStrength.getLevel() != currSignalStrength.getLevel()) { 9038 mLastNotifiedCarrierRoamingNtnSignalStrength.put(subId, currSignalStrength); 9039 phone.notifyCarrierRoamingNtnSignalStrengthChanged(currSignalStrength); 9040 } 9041 } 9042 } 9043 9044 /** Returns whether to send SMS to DatagramDispatcher or not. */ shouldSendSmsToDatagramDispatcher(@ullable Phone phone)9045 public boolean shouldSendSmsToDatagramDispatcher(@Nullable Phone phone) { 9046 final long identity = Binder.clearCallingIdentity(); 9047 try { 9048 if (!isInCarrierRoamingNbIotNtn(phone)) { 9049 return false; 9050 } 9051 9052 if (isDemoModeEnabled()) { 9053 return false; 9054 } 9055 9056 int[] services = getSupportedServicesOnCarrierRoamingNtn(phone.getSubId()); 9057 return ArrayUtils.contains(services, NetworkRegistrationInfo.SERVICE_TYPE_SMS); 9058 } finally { 9059 Binder.restoreCallingIdentity(identity); 9060 } 9061 } 9062 9063 /** Returns whether to drop SMS or not. */ shouldDropSms(@ullable Phone phone)9064 public boolean shouldDropSms(@Nullable Phone phone) { 9065 final long identity = Binder.clearCallingIdentity(); 9066 try { 9067 if (!isInCarrierRoamingNbIotNtn(phone)) { 9068 return false; 9069 } 9070 9071 int[] services = getSupportedServicesOnCarrierRoamingNtn(phone.getSubId()); 9072 return !ArrayUtils.contains(services, NetworkRegistrationInfo.SERVICE_TYPE_SMS); 9073 } finally { 9074 Binder.restoreCallingIdentity(identity); 9075 } 9076 } 9077 isWaitingForSatelliteModemOff()9078 private boolean isWaitingForSatelliteModemOff() { 9079 synchronized (mSatelliteEnabledRequestLock) { 9080 return mWaitingForSatelliteModemOff; 9081 } 9082 } 9083 9084 @Nullable getIsSatelliteSupported()9085 private Boolean getIsSatelliteSupported() { 9086 synchronized (mIsSatelliteSupportedLock) { 9087 return mIsSatelliteSupported; 9088 } 9089 } 9090 isWaitingForDisableSatelliteModemResponse()9091 private boolean isWaitingForDisableSatelliteModemResponse() { 9092 synchronized (mSatelliteEnabledRequestLock) { 9093 return mWaitingForDisableSatelliteModemResponse; 9094 } 9095 } 9096 isSatelliteAccessAllowedAtCurrentLocation()9097 private boolean isSatelliteAccessAllowedAtCurrentLocation() { 9098 synchronized (mSatelliteAccessConfigLock) { 9099 return mSatelliteAccessAllowed; 9100 } 9101 } 9102 9103 @Nullable getIsSatelliteEnabled()9104 private Boolean getIsSatelliteEnabled() { 9105 synchronized (mIsSatelliteEnabledLock) { 9106 return mIsSatelliteEnabled; 9107 } 9108 } 9109 9110 @Nullable getSatelliteDisabledRequest()9111 private RequestSatelliteEnabledArgument getSatelliteDisabledRequest() { 9112 synchronized (mSatelliteEnabledRequestLock) { 9113 return mSatelliteDisabledRequest; 9114 } 9115 } 9116 getSatelliteCapabilities()9117 private SatelliteCapabilities getSatelliteCapabilities() { 9118 synchronized (mSatelliteCapabilitiesLock) { 9119 return mSatelliteCapabilities; 9120 } 9121 } 9122 setBTEnabledState(boolean enabled)9123 private void setBTEnabledState(boolean enabled) { 9124 synchronized (mRadioStateLock) { 9125 mBTStateEnabled = enabled; 9126 } 9127 } 9128 getBTEnabledState()9129 private boolean getBTEnabledState() { 9130 synchronized (mRadioStateLock) { 9131 return mBTStateEnabled; 9132 } 9133 } 9134 setNfcEnabledState(boolean enabled)9135 private void setNfcEnabledState(boolean enabled) { 9136 synchronized (mRadioStateLock) { 9137 mNfcStateEnabled = enabled; 9138 } 9139 } 9140 getNfcEnabledState()9141 private boolean getNfcEnabledState() { 9142 synchronized (mRadioStateLock) { 9143 return mNfcStateEnabled; 9144 } 9145 } 9146 setUwbEnabledState(boolean enabled)9147 private void setUwbEnabledState(boolean enabled) { 9148 synchronized (mRadioStateLock) { 9149 mUwbStateEnabled = enabled; 9150 } 9151 } 9152 getUwbEnabledState()9153 private boolean getUwbEnabledState() { 9154 synchronized (mRadioStateLock) { 9155 return mUwbStateEnabled; 9156 } 9157 } 9158 setWifiEnabledState(boolean enabled)9159 private void setWifiEnabledState(boolean enabled) { 9160 synchronized (mRadioStateLock) { 9161 mWifiStateEnabled = enabled; 9162 } 9163 } 9164 getWifiEnabledState()9165 private boolean getWifiEnabledState() { 9166 synchronized (mRadioStateLock) { 9167 return mWifiStateEnabled; 9168 } 9169 } 9170 9171 /** 9172 * Method to return the current data plan for the registered plmn based on entitlement 9173 * provisioning information. Note: If no information at 9174 * provisioning is supported this is overridden with operator carrier config information. 9175 * 9176 * @param subId current subscription id 9177 * @param plmn current registered plmn information 9178 * 9179 * @return Data supported modes {@link SatelliteController#SATELLITE_DATA_PLAN_METERED} 9180 */ getSatelliteDataPlanForPlmn(int subId, String plmn)9181 public int getSatelliteDataPlanForPlmn(int subId, String plmn) { 9182 if (plmn != null) { 9183 synchronized (mSupportedSatelliteServicesLock) { 9184 Map<String, Integer> dataplanMap = mEntitlementDataPlanMapPerCarrier.get(subId); 9185 logd("data plan available for sub id:" + dataplanMap); 9186 if (dataplanMap != null && dataplanMap.containsKey(plmn)) { 9187 return dataplanMap.get(plmn); 9188 } 9189 } 9190 } 9191 // TODO (Override with carrier config value when configuration defined) 9192 return SATELLITE_DATA_PLAN_METERED; 9193 } 9194 9195 /** 9196 * Check if the available satellite services support 9197 * {@link NetworkRegistrationInfo#SERVICE_TYPE_DATA} service or not. 9198 * 9199 * @return {@code true} if data services is supported, otherwise {@code false}. 9200 */ isSatelliteDataServicesAllowed(int subId, String plmn)9201 private boolean isSatelliteDataServicesAllowed(int subId, String plmn) { 9202 // validate is available services support data, for satellite internet bringup 9203 List<Integer> availableServices = getSupportedSatelliteServicesForPlmn(subId, plmn); 9204 return availableServices.stream().anyMatch(num -> num 9205 == NetworkRegistrationInfo.SERVICE_TYPE_DATA); 9206 } 9207 9208 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) isLocationServiceEnabled()9209 protected boolean isLocationServiceEnabled() { 9210 LocationManager lm = mContext.createAttributionContext("telephony") 9211 .getSystemService(LocationManager.class); 9212 if (lm != null) { 9213 return lm.isLocationEnabled(); 9214 } 9215 9216 return true; 9217 } 9218 9219 /** 9220 * Method to return the current satellite data service policy supported mode for the registered 9221 * plmn based on entitlement provisioning information. Note: If no information at 9222 * provisioning is supported this is overridden with operator carrier config information 9223 * if available satellite services support data else data service policy is marked as 9224 * restricted. 9225 * 9226 * @param subId current subscription id 9227 * @param plmn current registered plmn information 9228 * 9229 * @return Supported modes {@link CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE} 9230 */ getSatelliteDataServicePolicyForPlmn(int subId, String plmn)9231 public int getSatelliteDataServicePolicyForPlmn(int subId, String plmn) { 9232 plogd("getSatelliteDataServicePolicyForPlmn: subId=" + subId + " plmn=" + plmn); 9233 if (isValidSubscriptionId(subId)) { 9234 Map<String, Integer> dataServicePolicy; 9235 synchronized (mSupportedSatelliteServicesLock) { 9236 dataServicePolicy = mEntitlementDataServicePolicyMapPerCarrier.get(subId); 9237 } 9238 plogd("getSatelliteDataServicePolicyForPlmn: dataServicePolicy=" + dataServicePolicy); 9239 9240 if (dataServicePolicy != null) { 9241 if (!TextUtils.isEmpty(plmn) && dataServicePolicy.containsKey(plmn)) { 9242 plogd("getSatelliteDataServicePolicyForPlmn: " 9243 + "return policy using dataServicePolicy map"); 9244 return dataServicePolicy.get(plmn); 9245 } else if (TextUtils.isEmpty(plmn)) { 9246 int preferredPolicy = 9247 CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED; 9248 for (String plmnKey : dataServicePolicy.keySet()) { 9249 int policy = dataServicePolicy.get(plmnKey); 9250 // higher value has higher preference 9251 if (policy > preferredPolicy) { 9252 preferredPolicy = policy; 9253 } 9254 } 9255 plogd("getSatelliteDataServicePolicyForPlmn: " 9256 + "return preferredPolicy=" + preferredPolicy); 9257 return preferredPolicy; 9258 } 9259 } 9260 9261 if (isSatelliteDataServicesAllowed(subId, plmn)) { 9262 plogd("getSatelliteDataServicePolicyForPlmn: return data support mode from config"); 9263 return getCarrierSatelliteDataSupportedModeFromConfig(subId); 9264 } 9265 } 9266 9267 plogd("getSatelliteDataServicePolicyForPlmn: return data support only restricted"); 9268 return CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED; 9269 } 9270 9271 /** 9272 * Method to return the current satellite voice service policy supported mode for the registered 9273 * plmn based on entitlement provisioning information. Note: If no information at 9274 * provisioning is supported this is overridden with operator carrier config information. 9275 * 9276 * @param subId current subscription id 9277 * @param plmn current registered plmn information 9278 * 9279 * @return Supported modes {@link CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE} 9280 */ getSatelliteVoiceServicePolicyForPlmn(int subId, String plmn)9281 public int getSatelliteVoiceServicePolicyForPlmn(int subId, String plmn) { 9282 if (plmn != null) { 9283 synchronized (mSupportedSatelliteServicesLock) { 9284 Map<String, Integer> voiceServicePolicy = 9285 mEntitlementVoiceServicePolicyMapPerCarrier.get( 9286 subId); 9287 logd("voice policy available for sub id:" + voiceServicePolicy); 9288 if (voiceServicePolicy != null && voiceServicePolicy.containsKey(plmn) 9289 && !plmn.isEmpty()) { 9290 return voiceServicePolicy.get(plmn); 9291 } 9292 } 9293 } 9294 // TODO (Replace below code with related enum value, when voice service policy support mode 9295 // is added) 9296 return 0; // Restricted 9297 } 9298 9299 /** 9300 * Get list of applications that are optimized for low bandwidth satellite data. 9301 * 9302 * @param userId is Identifier of user 9303 * 9304 * @return List of Application Name with data optimized network property. 9305 * {@link #PROPERTY_SATELLITE_DATA_OPTIMIZED} 9306 */ getSatelliteDataOptimizedApps(int userId)9307 public List<String> getSatelliteDataOptimizedApps(int userId) { 9308 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 9309 return mSatelliteOptimizedApplicationsTracker.getSatelliteOptimizedApplications(userId); 9310 } else { 9311 return new ArrayList<>(); 9312 } 9313 } 9314 9315 /** 9316 * Method to return the current satellite data service policy supported mode for the 9317 * subscription id based on carrier config. 9318 * 9319 * @param subId current subscription id. 9320 * 9321 * @return Supported modes {@link SatelliteManager#SatelliteDataSupportMode} 9322 * 9323 * @hide 9324 */ 9325 @SatelliteManager.SatelliteDataSupportMode getSatelliteDataSupportMode(int subId)9326 public int getSatelliteDataSupportMode(int subId) { 9327 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 9328 return SatelliteManager.SATELLITE_DATA_SUPPORT_RESTRICTED; 9329 } 9330 9331 return getSatelliteDataServicePolicyForPlmn(subId, ""); 9332 } 9333 9334 /** 9335 * This API can be used by only CTS to make the function {@link #getAllPlmnSet()} to exclude the 9336 * PLMN list from storage from the returned result. 9337 * 9338 * @param enabled Whether to enable boolean config. 9339 * @return {@code true} if the value is set successfully, {@code false} otherwise. 9340 */ setSatelliteIgnorePlmnListFromStorage(boolean enabled)9341 public boolean setSatelliteIgnorePlmnListFromStorage(boolean enabled) { 9342 plogd("setSatelliteIgnorePlmnListFromStorage - " + enabled); 9343 mIgnorePlmnListFromStorage.set(enabled); 9344 return true; 9345 } 9346 } 9347