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.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT; 20 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT; 21 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT; 22 import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SMS; 23 import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE; 24 import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN; 25 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE; 26 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED; 27 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE; 28 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS; 29 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING; 30 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING; 31 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED; 32 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS; 33 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN; 34 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT; 35 import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED; 36 import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING; 37 import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_ENABLING_SATELLITE; 38 import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_IDLE; 39 import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_LISTENING; 40 import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN; 41 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED; 42 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS; 43 44 import android.annotation.NonNull; 45 import android.annotation.Nullable; 46 import android.app.AlarmManager; 47 import android.content.ComponentName; 48 import android.content.Context; 49 import android.content.Intent; 50 import android.content.ServiceConnection; 51 import android.os.AsyncResult; 52 import android.os.Build; 53 import android.os.HandlerExecutor; 54 import android.os.IBinder; 55 import android.os.Looper; 56 import android.os.Message; 57 import android.os.PersistableBundle; 58 import android.os.RemoteException; 59 import android.os.SystemClock; 60 import android.os.SystemProperties; 61 import android.os.WorkSource; 62 import android.telephony.NetworkRegistrationInfo; 63 import android.telephony.PersistentLogger; 64 import android.telephony.ServiceState; 65 import android.telephony.satellite.ISatelliteModemStateCallback; 66 import android.telephony.satellite.SatelliteManager; 67 import android.telephony.satellite.stub.ISatelliteGateway; 68 import android.telephony.satellite.stub.SatelliteGatewayService; 69 import android.text.TextUtils; 70 import android.util.Log; 71 72 import com.android.internal.R; 73 import com.android.internal.annotations.VisibleForTesting; 74 import com.android.internal.telephony.DeviceStateMonitor; 75 import com.android.internal.telephony.ExponentialBackoff; 76 import com.android.internal.telephony.IIntegerConsumer; 77 import com.android.internal.telephony.Phone; 78 import com.android.internal.telephony.PhoneFactory; 79 import com.android.internal.telephony.flags.FeatureFlags; 80 import com.android.internal.telephony.satellite.metrics.SessionMetricsStats; 81 import com.android.internal.telephony.util.ArrayUtils; 82 import com.android.internal.util.State; 83 import com.android.internal.util.StateMachine; 84 import com.android.telephony.Rlog; 85 86 import java.util.ArrayList; 87 import java.util.List; 88 import java.util.concurrent.ConcurrentHashMap; 89 import java.util.concurrent.atomic.AtomicBoolean; 90 91 /** 92 * This module is responsible for managing session state transition and inform listeners of modem 93 * state changed events accordingly. 94 */ 95 public class SatelliteSessionController extends StateMachine { 96 private static final String TAG = "SatelliteSessionController"; 97 private static final boolean DBG = true; 98 private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem"; 99 private static final boolean DEBUG = !"user".equals(Build.TYPE); 100 101 /** 102 * The time duration in millis that the satellite will stay at listening mode to wait for the 103 * next incoming page before disabling listening mode when transitioning from sending mode. 104 */ 105 public static final String SATELLITE_STAY_AT_LISTENING_FROM_SENDING_MILLIS = 106 "satellite_stay_at_listening_from_sending_millis"; 107 /** 108 * The default value of {@link #SATELLITE_STAY_AT_LISTENING_FROM_SENDING_MILLIS}. 109 */ 110 public static final long DEFAULT_SATELLITE_STAY_AT_LISTENING_FROM_SENDING_MILLIS = 180000; 111 /** 112 * The time duration in millis that the satellite will stay at listening mode to wait for the 113 * next incoming page before disabling listening mode when transitioning from receiving mode. 114 */ 115 public static final String SATELLITE_STAY_AT_LISTENING_FROM_RECEIVING_MILLIS = 116 "satellite_stay_at_listening_from_receiving_millis"; 117 /** 118 * The default value of {@link #SATELLITE_STAY_AT_LISTENING_FROM_RECEIVING_MILLIS} 119 */ 120 public static final long DEFAULT_SATELLITE_STAY_AT_LISTENING_FROM_RECEIVING_MILLIS = 30000; 121 /** 122 * The default value of {@link #SATELLITE_STAY_AT_LISTENING_FROM_SENDING_MILLIS}, 123 * and {@link #SATELLITE_STAY_AT_LISTENING_FROM_RECEIVING_MILLIS} for demo mode 124 */ 125 public static final long DEMO_MODE_SATELLITE_STAY_AT_LISTENING_MILLIS = 3000; 126 127 private static final int EVENT_DATAGRAM_TRANSFER_STATE_CHANGED = 1; 128 private static final int EVENT_LISTENING_TIMER_TIMEOUT = 2; 129 private static final int EVENT_SATELLITE_ENABLED_STATE_CHANGED = 3; 130 private static final int EVENT_SATELLITE_MODEM_STATE_CHANGED = 4; 131 private static final int EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE = 5; 132 protected static final int EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT = 6; 133 private static final int EVENT_SATELLITE_ENABLEMENT_STARTED = 7; 134 private static final int EVENT_SATELLITE_ENABLEMENT_FAILED = 8; 135 private static final int EVENT_SCREEN_STATE_CHANGED = 9; 136 protected static final int EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT = 10; 137 protected static final int EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT = 11; 138 private static final int EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE = 12; 139 private static final int EVENT_SERVICE_STATE_CHANGED = 13; 140 protected static final int EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT = 14; 141 142 private static final long REBIND_INITIAL_DELAY = 2 * 1000; // 2 seconds 143 private static final long REBIND_MAXIMUM_DELAY = 64 * 1000; // 1 minute 144 private static final int REBIND_MULTIPLIER = 2; 145 private static final int DEFAULT_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC = 30; 146 private static final int DEFAULT_P2P_SMS_INACTIVITY_TIMEOUT_SEC = 180; 147 private static final int DEFAULT_ESOS_INACTIVITY_TIMEOUT_SEC = 600; 148 private static final long UNDEFINED_TIMESTAMP = 0L; 149 150 @NonNull private final ExponentialBackoff mExponentialBackoff; 151 @NonNull private final Object mLock = new Object(); 152 @Nullable 153 private ISatelliteGateway mSatelliteGatewayService; 154 private String mSatelliteGatewayServicePackageName = ""; 155 @Nullable private SatelliteGatewayServiceConnection mSatelliteGatewayServiceConnection; 156 private boolean mIsBound; 157 private boolean mIsBinding; 158 private boolean mIsRegisteredScreenStateChanged = false; 159 160 @NonNull private static SatelliteSessionController sInstance; 161 162 @NonNull private final Context mContext; 163 @NonNull private final SatelliteModemInterface mSatelliteModemInterface; 164 @NonNull private final UnavailableState mUnavailableState = new UnavailableState(); 165 @NonNull private final PowerOffState mPowerOffState = new PowerOffState(); 166 @NonNull private final EnablingState mEnablingState = new EnablingState(); 167 @NonNull private final DisablingState mDisablingState = new DisablingState(); 168 @NonNull private final IdleState mIdleState = new IdleState(); 169 @NonNull private final TransferringState mTransferringState = new TransferringState(); 170 @NonNull private final ListeningState mListeningState = new ListeningState(); 171 @NonNull private final NotConnectedState mNotConnectedState = new NotConnectedState(); 172 @NonNull private final ConnectedState mConnectedState = new ConnectedState(); 173 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 174 protected AtomicBoolean mIsSendingTriggeredDuringTransferringState; 175 private long mSatelliteStayAtListeningFromSendingMillis; 176 private long mSatelliteStayAtListeningFromReceivingMillis; 177 private long mSatelliteNbIotInactivityTimeoutMillis; 178 private boolean mIgnoreCellularServiceState = false; 179 private Boolean mIsConcurrentTnScanningSupportedForCtsTest = null; 180 private Boolean mIsTnScanningDuringSatelliteSessionAllowedForCtsTest = null; 181 private final ConcurrentHashMap<IBinder, ISatelliteModemStateCallback> mListeners; 182 @SatelliteManager.SatelliteModemState private int mCurrentState; 183 @SatelliteManager.SatelliteModemState private int mPreviousState; 184 final boolean mIsSatelliteSupported; 185 private boolean mIsDemoMode = false; 186 // Interested in screen off, so use default value true 187 boolean mIsScreenOn = true; 188 private boolean mIsDeviceAlignedWithSatellite = false; 189 private long mInactivityStartTimestamp = UNDEFINED_TIMESTAMP; 190 private DatagramTransferState mLastDatagramTransferState = 191 new DatagramTransferState( 192 SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN, 193 SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN, 194 DATAGRAM_TYPE_UNKNOWN); 195 196 @NonNull private final SatelliteController mSatelliteController; 197 @NonNull private final DatagramController mDatagramController; 198 @Nullable private PersistentLogger mPersistentLogger = null; 199 @Nullable private DeviceStateMonitor mDeviceStateMonitor; 200 @NonNull private SessionMetricsStats mSessionMetricsStats; 201 @NonNull private FeatureFlags mFeatureFlags; 202 @NonNull private AlarmManager mAlarmManager; 203 private final AlarmManager.OnAlarmListener mAlarmListener = new AlarmManager.OnAlarmListener() { 204 @Override 205 public void onAlarm() { 206 plogd("onAlarm: screen off timer expired"); 207 sendMessage(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT); 208 } 209 }; 210 211 /** 212 * @return The singleton instance of SatelliteSessionController. 213 */ getInstance()214 public static SatelliteSessionController getInstance() { 215 if (sInstance == null) { 216 Log.e(TAG, "SatelliteSessionController was not yet initialized."); 217 } 218 return sInstance; 219 } 220 221 /** 222 * Create the SatelliteSessionController singleton instance. 223 * 224 * @param context The Context for the SatelliteSessionController. 225 * @param looper The looper associated with the handler of this class. 226 * @param featureFlags The telephony feature flags. 227 * @param isSatelliteSupported Whether satellite is supported on the device. 228 * @return The singleton instance of SatelliteSessionController. 229 */ make( @onNull Context context, @NonNull Looper looper, @NonNull FeatureFlags featureFlags, boolean isSatelliteSupported)230 public static SatelliteSessionController make( 231 @NonNull Context context, 232 @NonNull Looper looper, 233 @NonNull FeatureFlags featureFlags, 234 boolean isSatelliteSupported) { 235 if (sInstance == null || isSatelliteSupported != sInstance.mIsSatelliteSupported) { 236 ConcurrentHashMap<IBinder, ISatelliteModemStateCallback> existingListeners = null; 237 boolean existIgnoreCellularServiceState = false; 238 if (sInstance != null) { 239 existingListeners = sInstance.mListeners; 240 existIgnoreCellularServiceState = sInstance.mIgnoreCellularServiceState; 241 sInstance.cleanUpResource(); 242 } 243 244 sInstance = new SatelliteSessionController( 245 context, 246 looper, 247 featureFlags, 248 isSatelliteSupported, 249 SatelliteModemInterface.getInstance()); 250 if (existingListeners != null) { 251 Log.d(TAG, "make() existingListeners: " + existingListeners.size()); 252 sInstance.mListeners.putAll(existingListeners); 253 } 254 if (existIgnoreCellularServiceState) { 255 Log.d(TAG, "make() existIgnoreCellularServiceState is true"); 256 sInstance.mIgnoreCellularServiceState = true; 257 } 258 } 259 return sInstance; 260 } 261 262 /** 263 * Create a SatelliteSessionController to manage satellite session. 264 * 265 * @param context The Context for the SatelliteSessionController. 266 * @param looper The looper associated with the handler of this class. 267 * @param featureFlags The telephony feature flags. 268 * @param isSatelliteSupported Whether satellite is supported on the device. 269 * @param satelliteModemInterface The singleton of SatelliteModemInterface. 270 */ 271 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) SatelliteSessionController(@onNull Context context, @NonNull Looper looper, @NonNull FeatureFlags featureFlags, boolean isSatelliteSupported, @NonNull SatelliteModemInterface satelliteModemInterface)272 protected SatelliteSessionController(@NonNull Context context, @NonNull Looper looper, 273 @NonNull FeatureFlags featureFlags, 274 boolean isSatelliteSupported, 275 @NonNull SatelliteModemInterface satelliteModemInterface) { 276 super(TAG, looper); 277 278 mPersistentLogger = SatelliteServiceUtils.getPersistentLogger(context); 279 mContext = context; 280 mFeatureFlags = featureFlags; 281 mSatelliteModemInterface = satelliteModemInterface; 282 mSatelliteController = SatelliteController.getInstance(); 283 mDatagramController = DatagramController.getInstance(); 284 mSatelliteStayAtListeningFromSendingMillis = getSatelliteStayAtListeningFromSendingMillis(); 285 mSatelliteStayAtListeningFromReceivingMillis = 286 getSatelliteStayAtListeningFromReceivingMillis(); 287 mSatelliteNbIotInactivityTimeoutMillis = 288 getSatelliteNbIotInactivityTimeoutMillis(); 289 mListeners = new ConcurrentHashMap<>(); 290 mIsSendingTriggeredDuringTransferringState = new AtomicBoolean(false); 291 mPreviousState = SATELLITE_MODEM_STATE_UNKNOWN; 292 mCurrentState = SATELLITE_MODEM_STATE_UNKNOWN; 293 mIsSatelliteSupported = isSatelliteSupported; 294 mExponentialBackoff = new ExponentialBackoff(REBIND_INITIAL_DELAY, REBIND_MAXIMUM_DELAY, 295 REBIND_MULTIPLIER, looper, () -> { 296 synchronized (mLock) { 297 if ((mIsBound && mSatelliteGatewayService != null) || mIsBinding) { 298 return; 299 } 300 } 301 if (mSatelliteGatewayServiceConnection != null) { 302 synchronized (mLock) { 303 mIsBound = false; 304 mIsBinding = false; 305 } 306 unbindService(); 307 } 308 bindService(); 309 }); 310 311 Phone satellitePhone = mSatelliteController.getSatellitePhone(); 312 if (satellitePhone == null) { 313 satellitePhone = SatelliteServiceUtils.getPhone(); 314 } 315 mDeviceStateMonitor = satellitePhone.getDeviceStateMonitor(); 316 mSessionMetricsStats = SessionMetricsStats.getInstance(); 317 mAlarmManager = mContext.getSystemService(AlarmManager.class); 318 319 addState(mUnavailableState); 320 addState(mPowerOffState); 321 addState(mEnablingState); 322 addState(mDisablingState); 323 addState(mIdleState); 324 addState(mTransferringState); 325 addState(mListeningState); 326 addState(mNotConnectedState); 327 addState(mConnectedState); 328 setInitialState(isSatelliteSupported); 329 start(); 330 } 331 332 /** 333 * {@link DatagramController} uses this function to notify {@link SatelliteSessionController} 334 * that its datagram transfer state has changed. 335 * 336 * @param sendState The current datagram send state of {@link DatagramController}. 337 * @param receiveState The current datagram receive state of {@link DatagramController}. 338 */ 339 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) onDatagramTransferStateChanged( @atelliteManager.SatelliteDatagramTransferState int sendState, @SatelliteManager.SatelliteDatagramTransferState int receiveState, @SatelliteManager.DatagramType int datagramType)340 public void onDatagramTransferStateChanged( 341 @SatelliteManager.SatelliteDatagramTransferState int sendState, 342 @SatelliteManager.SatelliteDatagramTransferState int receiveState, 343 @SatelliteManager.DatagramType int datagramType) { 344 DatagramTransferState datagramTransferState = 345 new DatagramTransferState(sendState, receiveState, datagramType); 346 mLastDatagramTransferState = datagramTransferState; 347 348 sendMessage(EVENT_DATAGRAM_TRANSFER_STATE_CHANGED, datagramTransferState); 349 350 if (sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING) { 351 mIsSendingTriggeredDuringTransferringState.set(true); 352 } 353 354 if (datagramTransferState.isIdle()) { 355 checkForInactivity(); 356 } else { 357 endUserInactivity(); 358 } 359 } 360 361 /** 362 * {@link SatelliteController} uses this function to notify {@link SatelliteSessionController} 363 * that the satellite enabled state has changed. 364 * 365 * @param enabled {@code true} means enabled and {@code false} means disabled. 366 */ 367 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) onSatelliteEnabledStateChanged(boolean enabled)368 public void onSatelliteEnabledStateChanged(boolean enabled) { 369 sendMessage(EVENT_SATELLITE_ENABLED_STATE_CHANGED, enabled); 370 } 371 372 /** 373 * {@link SatelliteController} uses this function to notify {@link SatelliteSessionController} 374 * that the satellite enablement has just started. 375 * 376 * @param enabled {@code true} means being enabled and {@code false} means being disabled. 377 */ 378 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) onSatelliteEnablementStarted(boolean enabled)379 public void onSatelliteEnablementStarted(boolean enabled) { 380 sendMessage(EVENT_SATELLITE_ENABLEMENT_STARTED, enabled); 381 } 382 383 /** 384 * {@link SatelliteController} uses this function to notify {@link SatelliteSessionController} 385 * that the satellite enablement has just failed. 386 * 387 * @param enabled {@code true} if satellite is enabled, {@code false} satellite is disabled. 388 */ 389 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) onSatelliteEnablementFailed(boolean enabled)390 public void onSatelliteEnablementFailed(boolean enabled) { 391 sendMessage(EVENT_SATELLITE_ENABLEMENT_FAILED, enabled); 392 } 393 394 /** 395 * {@link SatelliteController} uses this function to notify {@link SatelliteSessionController} 396 * that the satellite modem state has changed. 397 * 398 * @param state The current state of the satellite modem. 399 */ 400 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) onSatelliteModemStateChanged(@atelliteManager.SatelliteModemState int state)401 public void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state) { 402 sendMessage(EVENT_SATELLITE_MODEM_STATE_CHANGED, state); 403 } 404 405 /** 406 * {@link SatelliteController} uses this function to notify {@link SatelliteSessionController} 407 * that the satellite emergency mode has changed. 408 * 409 * @param isEmergencyMode The satellite emergency mode. 410 */ onEmergencyModeChanged(boolean isEmergencyMode)411 public void onEmergencyModeChanged(boolean isEmergencyMode) { 412 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 413 plogd("onEmergencyModeChanged: carrierRoamingNbIotNtn is disabled"); 414 return; 415 } 416 417 plogd("onEmergencyModeChanged " + isEmergencyMode); 418 419 List<ISatelliteModemStateCallback> toBeRemoved = new ArrayList<>(); 420 mListeners.values().forEach(listener -> { 421 try { 422 listener.onEmergencyModeChanged(isEmergencyMode); 423 } catch (RemoteException e) { 424 plogd("onEmergencyModeChanged RemoteException: " + e); 425 toBeRemoved.add(listener); 426 } 427 }); 428 429 toBeRemoved.forEach(listener -> { 430 mListeners.remove(listener.asBinder()); 431 }); 432 } 433 434 /** 435 * Registers for modem state changed from satellite modem. 436 * 437 * @param callback The callback to handle the satellite modem state changed event. 438 */ registerForSatelliteModemStateChanged( @onNull ISatelliteModemStateCallback callback)439 public void registerForSatelliteModemStateChanged( 440 @NonNull ISatelliteModemStateCallback callback) { 441 try { 442 callback.onSatelliteModemStateChanged(mCurrentState); 443 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 444 callback.onEmergencyModeChanged(mSatelliteController.getRequestIsEmergency()); 445 } 446 mListeners.put(callback.asBinder(), callback); 447 } catch (RemoteException ex) { 448 ploge("registerForSatelliteModemStateChanged: Got RemoteException ex=" + ex); 449 } 450 } 451 452 /** 453 * Unregisters for modem state changed from satellite modem. 454 * If callback was not registered before, the request will be ignored. 455 * 456 * @param callback The callback that was passed to 457 * {@link #registerForSatelliteModemStateChanged(ISatelliteModemStateCallback)}. 458 */ unregisterForSatelliteModemStateChanged( @onNull ISatelliteModemStateCallback callback)459 public void unregisterForSatelliteModemStateChanged( 460 @NonNull ISatelliteModemStateCallback callback) { 461 mListeners.remove(callback.asBinder()); 462 } 463 464 /** 465 * This API can be used by only CTS to update the timeout duration in milliseconds that 466 * satellite should stay at listening mode to wait for the next incoming page before disabling 467 * listening mode. 468 * 469 * @param timeoutMillis The timeout duration in millisecond. 470 * @return {@code true} if the timeout duration is set successfully, {@code false} otherwise. 471 */ setSatelliteListeningTimeoutDuration(long timeoutMillis)472 boolean setSatelliteListeningTimeoutDuration(long timeoutMillis) { 473 if (!isMockModemAllowed()) { 474 ploge("Updating listening timeout duration is not allowed"); 475 return false; 476 } 477 478 plogd("setSatelliteListeningTimeoutDuration: timeoutMillis=" + timeoutMillis); 479 if (timeoutMillis == 0) { 480 mSatelliteStayAtListeningFromSendingMillis = 481 getSatelliteStayAtListeningFromSendingMillis(); 482 mSatelliteStayAtListeningFromReceivingMillis = 483 getSatelliteStayAtListeningFromReceivingMillis(); 484 mSatelliteNbIotInactivityTimeoutMillis = 485 getSatelliteNbIotInactivityTimeoutMillis(); 486 } else { 487 mSatelliteStayAtListeningFromSendingMillis = timeoutMillis; 488 mSatelliteStayAtListeningFromReceivingMillis = timeoutMillis; 489 mSatelliteNbIotInactivityTimeoutMillis = timeoutMillis; 490 } 491 492 return true; 493 } 494 495 /** 496 * This API can be used by only CTS to control ingoring cellular service state event. 497 * 498 * @param enabled Whether to enable boolean config. 499 * @return {@code true} if the value is set successfully, {@code false} otherwise. 500 */ setSatelliteIgnoreCellularServiceState(boolean enabled)501 public boolean setSatelliteIgnoreCellularServiceState(boolean enabled) { 502 plogd("setSatelliteIgnoreCellularServiceState : " 503 + "old = " + mIgnoreCellularServiceState + " new : " + enabled); 504 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 505 return false; 506 } 507 508 mIgnoreCellularServiceState = enabled; 509 return true; 510 } 511 512 /** 513 * This API can be used by only CTS to update satellite gateway service package name. 514 * 515 * @param servicePackageName The package name of the satellite gateway service. 516 * @return {@code true} if the satellite gateway service is set successfully, 517 * {@code false} otherwise. 518 */ setSatelliteGatewayServicePackageName(@ullable String servicePackageName)519 boolean setSatelliteGatewayServicePackageName(@Nullable String servicePackageName) { 520 if (!isMockModemAllowed()) { 521 ploge("setSatelliteGatewayServicePackageName: modifying satellite gateway service " 522 + "package name is not allowed"); 523 return false; 524 } 525 526 plogd("setSatelliteGatewayServicePackageName: config_satellite_gateway_service_package is " 527 + "updated, new packageName=" + servicePackageName); 528 529 if (servicePackageName == null || servicePackageName.equals("null")) { 530 mSatelliteGatewayServicePackageName = ""; 531 } else { 532 mSatelliteGatewayServicePackageName = servicePackageName; 533 } 534 535 if (mSatelliteGatewayServiceConnection != null) { 536 synchronized (mLock) { 537 mIsBound = false; 538 mIsBinding = false; 539 } 540 unbindService(); 541 bindService(); 542 } 543 return true; 544 } 545 546 /** 547 * This API can be used by only CTS to override TN scanning support. 548 * 549 * @param concurrentTnScanningSupported Whether concurrent TN scanning is supported. 550 * @param tnScanningDuringSatelliteSessionAllowed Whether TN scanning is allowed during 551 * a satellite session. 552 * @return {@code true} if the TN scanning support is set successfully, 553 * {@code false} otherwise. 554 */ setTnScanningSupport(boolean reset, boolean concurrentTnScanningSupported, boolean tnScanningDuringSatelliteSessionAllowed)555 boolean setTnScanningSupport(boolean reset, boolean concurrentTnScanningSupported, 556 boolean tnScanningDuringSatelliteSessionAllowed) { 557 if (!isMockModemAllowed()) { 558 ploge("setTnScanningSupport: modifying TN scanning support is not allowed"); 559 return false; 560 } 561 562 plogd("setTnScanningSupport: reset=" + reset 563 + ", concurrentTnScanningSupported=" + concurrentTnScanningSupported 564 + ", tnScanningDuringSatelliteSessionAllowed=" 565 + tnScanningDuringSatelliteSessionAllowed); 566 if (reset) { 567 mIsConcurrentTnScanningSupportedForCtsTest = null; 568 mIsTnScanningDuringSatelliteSessionAllowedForCtsTest = null; 569 } else { 570 mIsConcurrentTnScanningSupportedForCtsTest = concurrentTnScanningSupported; 571 mIsTnScanningDuringSatelliteSessionAllowedForCtsTest = 572 tnScanningDuringSatelliteSessionAllowed; 573 } 574 return true; 575 } 576 577 /** 578 * Adjusts listening timeout duration when demo mode is on 579 * 580 * @param isDemoMode {@code true} : The listening timeout durations will be set to 581 * {@link #DEMO_MODE_SATELLITE_STAY_AT_LISTENING_MILLIS} 582 * {@code false} : The listening timeout durations will be restored to 583 * production mode 584 */ 585 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) setDemoMode(boolean isDemoMode)586 public void setDemoMode(boolean isDemoMode) { 587 mIsDemoMode = isDemoMode; 588 } 589 590 /** 591 * Notify whether the device is aligned with the satellite 592 * 593 * @param isAligned {@code true} Device is aligned with the satellite, 594 * {@code false} otherwise. 595 */ setDeviceAlignedWithSatellite(boolean isAligned)596 public void setDeviceAlignedWithSatellite(boolean isAligned) { 597 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 598 plogd("setDeviceAlignedWithSatellite: carrierRoamingNbIotNtn is disabled"); 599 return; 600 } 601 602 mIsDeviceAlignedWithSatellite = isAligned; 603 plogd("setDeviceAlignedWithSatellite: isAligned " + isAligned); 604 605 if (mIsDeviceAlignedWithSatellite) { 606 stopEsosInactivityTimer(); 607 stopP2pSmsInactivityTimer(); 608 endUserInactivity(); 609 } else { 610 if (mCurrentState == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED 611 || mCurrentState == SATELLITE_MODEM_STATE_CONNECTED 612 || mCurrentState == SATELLITE_MODEM_STATE_IDLE) { 613 evaluateStartingEsosInactivityTimer(); 614 evaluateStartingP2pSmsInactivityTimer(); 615 } 616 checkForInactivity(); 617 } 618 } 619 620 /** 621 * Get whether state machine is in enabling state. 622 * 623 * @return {@code true} if state machine is in enabling state and {@code false} otherwise. 624 */ isInEnablingState()625 public boolean isInEnablingState() { 626 if (DBG) plogd("isInEnablingState: getCurrentState=" + getCurrentState()); 627 return getCurrentState() == mEnablingState; 628 } 629 630 /** 631 * Get whether state machine is in disabling state. 632 * 633 * @return {@code true} if state machine is in disabling state and {@code false} otherwise. 634 */ isInDisablingState()635 public boolean isInDisablingState() { 636 if (DBG) plogd("isInDisablingState: getCurrentState=" + getCurrentState()); 637 return getCurrentState() == mDisablingState; 638 } 639 640 /** 641 * Release all resource. 642 */ 643 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) cleanUpResource()644 public void cleanUpResource() { 645 plogd("cleanUpResource"); 646 mIsDeviceAlignedWithSatellite = false; 647 mInactivityStartTimestamp = UNDEFINED_TIMESTAMP; 648 unregisterForScreenStateChanged(); 649 if (mAlarmManager != null) { 650 mAlarmManager.cancel(mAlarmListener); 651 } 652 653 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 654 // Register to received Cellular service state 655 for (Phone phone : PhoneFactory.getPhones()) { 656 if (phone == null) continue; 657 658 phone.unregisterForServiceStateChanged(getHandler()); 659 if (DBG) { 660 plogd("cleanUpResource: unregisterForServiceStateChanged phoneId " 661 + phone.getPhoneId()); 662 } 663 } 664 } 665 666 quitNow(); 667 } 668 669 /** 670 * Uses this function to notify that cellular service state has changed 671 * 672 * @param serviceState The state of the cellular service. 673 */ 674 @VisibleForTesting onCellularServiceStateChanged(ServiceState serviceState)675 public void onCellularServiceStateChanged(ServiceState serviceState) { 676 sendMessage(EVENT_SERVICE_STATE_CHANGED, new AsyncResult(null, serviceState, null)); 677 } 678 679 /** 680 * Uses this function to set AlarmManager object for testing. 681 * 682 * @param alarmManager The instance of AlarmManager. 683 */ 684 @VisibleForTesting setAlarmManager(AlarmManager alarmManager)685 public void setAlarmManager(AlarmManager alarmManager) { 686 mAlarmManager = alarmManager; 687 } 688 isDemoMode()689 private boolean isDemoMode() { 690 return mIsDemoMode; 691 } 692 693 private static class DatagramTransferState { 694 @SatelliteManager.SatelliteDatagramTransferState public int sendState; 695 @SatelliteManager.SatelliteDatagramTransferState public int receiveState; 696 @SatelliteManager.DatagramType public int datagramType; 697 DatagramTransferState(@atelliteManager.SatelliteDatagramTransferState int sendState, @SatelliteManager.SatelliteDatagramTransferState int receiveState, @SatelliteManager.DatagramType int datagramType)698 DatagramTransferState(@SatelliteManager.SatelliteDatagramTransferState int sendState, 699 @SatelliteManager.SatelliteDatagramTransferState int receiveState, 700 @SatelliteManager.DatagramType int datagramType) { 701 this.sendState = sendState; 702 this.receiveState = receiveState; 703 this.datagramType = datagramType; 704 } 705 isIdle()706 public boolean isIdle() { 707 return (sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE 708 && receiveState == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE); 709 } 710 } 711 712 private class UnavailableState extends State { 713 @Override enter()714 public void enter() { 715 if (DBG) plogd("Entering UnavailableState"); 716 mPreviousState = mCurrentState; 717 mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE; 718 notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE); 719 } 720 721 @Override processMessage(Message msg)722 public boolean processMessage(Message msg) { 723 ploge("UnavailableState: receive msg " + getWhatToString(msg.what) + " unexpectedly"); 724 return HANDLED; 725 } 726 } 727 728 private class PowerOffState extends State { 729 @Override enter()730 public void enter() { 731 if (DBG) plogd("Entering PowerOffState"); 732 733 mSatelliteController.moveSatelliteToOffStateAndCleanUpResources( 734 SATELLITE_RESULT_REQUEST_ABORTED); 735 mPreviousState = mCurrentState; 736 mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_OFF; 737 mIsSendingTriggeredDuringTransferringState.set(false); 738 unbindService(); 739 stopNbIotInactivityTimer(); 740 stopEsosInactivityTimer(); 741 stopP2pSmsInactivityTimer(); 742 endUserInactivity(); 743 DemoSimulator.getInstance().onSatelliteModeOff(); 744 notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_OFF); 745 746 unregisterForScreenStateChanged(); 747 } 748 749 @Override exit()750 public void exit() { 751 if (DBG) plogd("Exiting PowerOffState"); 752 plogd("Attempting to bind to SatelliteGatewayService."); 753 bindService(); 754 } 755 756 @Override processMessage(Message msg)757 public boolean processMessage(Message msg) { 758 if (DBG) plogd("PowerOffState: processing " + getWhatToString(msg.what)); 759 switch (msg.what) { 760 case EVENT_SATELLITE_ENABLEMENT_STARTED: 761 handleSatelliteEnablementStarted((boolean) msg.obj); 762 break; 763 } 764 // Ignore all unexpected events. 765 return HANDLED; 766 } 767 handleSatelliteEnablementStarted(boolean enabled)768 private void handleSatelliteEnablementStarted(boolean enabled) { 769 if (enabled) { 770 transitionTo(mEnablingState); 771 } else { 772 plogw("Unexpected satellite disablement started in PowerOff state"); 773 } 774 } 775 } 776 777 private class EnablingState extends State { 778 @Override enter()779 public void enter() { 780 if (DBG) plogd("Entering EnablingState"); 781 782 mPreviousState = mCurrentState; 783 mCurrentState = SATELLITE_MODEM_STATE_ENABLING_SATELLITE; 784 notifyStateChangedEvent(SATELLITE_MODEM_STATE_ENABLING_SATELLITE); 785 } 786 787 @Override exit()788 public void exit() { 789 if (DBG) plogd("Exiting EnablingState"); 790 } 791 792 @Override processMessage(Message msg)793 public boolean processMessage(Message msg) { 794 if (DBG) plogd("EnablingState: processing " + getWhatToString(msg.what)); 795 switch (msg.what) { 796 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 797 handleSatelliteEnabledStateChanged((boolean) msg.obj); 798 break; 799 case EVENT_SATELLITE_ENABLEMENT_FAILED: 800 if ((boolean) msg.obj) { 801 transitionTo(mPowerOffState); 802 } else { 803 ploge("Unexpected failed disable event in EnablingState"); 804 } 805 break; 806 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 807 handleSatelliteModemStateChanged(msg); 808 break; 809 case EVENT_SATELLITE_ENABLEMENT_STARTED: 810 handleSatelliteEnablementStarted((boolean) msg.obj); 811 break; 812 } 813 // Ignore all unexpected events. 814 return HANDLED; 815 } 816 handleSatelliteEnabledStateChanged(boolean on)817 private void handleSatelliteEnabledStateChanged(boolean on) { 818 if (on) { 819 if (mSatelliteController.isSatelliteAttachRequired()) { 820 transitionTo(mNotConnectedState); 821 } else { 822 transitionTo(mIdleState); 823 } 824 DemoSimulator.getInstance().onSatelliteModeOn(); 825 826 registerForScreenStateChanged(); 827 } else { 828 /* 829 * During the state transition from ENABLING to NOT_CONNECTED, modem might be 830 * reset. In such cases, we need to remove all deferred 831 * EVENT_SATELLITE_MODEM_STATE_CHANGED events so that they will not mess up our 832 * state machine later. 833 */ 834 removeDeferredMessages(EVENT_SATELLITE_MODEM_STATE_CHANGED); 835 transitionTo(mPowerOffState); 836 } 837 } 838 handleSatelliteModemStateChanged(@onNull Message msg)839 private void handleSatelliteModemStateChanged(@NonNull Message msg) { 840 int state = msg.arg1; 841 if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) { 842 transitionTo(mPowerOffState); 843 } else { 844 deferMessage(msg); 845 } 846 } 847 } 848 849 private class DisablingState extends State { 850 @Override enter()851 public void enter() { 852 if (DBG) plogd("Entering DisablingState"); 853 854 mPreviousState = mCurrentState; 855 mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_DISABLING_SATELLITE; 856 notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_DISABLING_SATELLITE); 857 858 unregisterForScreenStateChanged(); 859 } 860 861 @Override exit()862 public void exit() { 863 if (DBG) plogd("Exiting DisablingState"); 864 } 865 866 @Override processMessage(Message msg)867 public boolean processMessage(Message msg) { 868 if (DBG) plogd("DisablingState: processing " + getWhatToString(msg.what)); 869 switch (msg.what) { 870 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 871 handleSatelliteEnabledStateChanged((boolean) msg.obj); 872 break; 873 case EVENT_SATELLITE_ENABLEMENT_FAILED: 874 boolean enablingSatellite = (boolean) msg.obj; 875 if (enablingSatellite) { 876 /* Framework received a disable request when the enable request was in 877 * progress. We need to set the previous state to OFF since the enable has 878 * failed so that when disable fail, we can move to OFF state properly. 879 */ 880 mPreviousState = SatelliteManager.SATELLITE_MODEM_STATE_OFF; 881 plogd("Enable request has failed. Set mPreviousState to OFF"); 882 break; 883 } 884 if (mPreviousState == SATELLITE_MODEM_STATE_CONNECTED 885 || mPreviousState == SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING 886 || mPreviousState == SATELLITE_MODEM_STATE_LISTENING) { 887 transitionTo(mConnectedState); 888 } else if (mPreviousState == SATELLITE_MODEM_STATE_ENABLING_SATELLITE) { 889 transitionTo(mEnablingState); 890 } else if (mPreviousState == SatelliteManager.SATELLITE_MODEM_STATE_OFF) { 891 transitionTo(mPowerOffState); 892 } else { 893 transitionTo(mNotConnectedState); 894 } 895 break; 896 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 897 handleEventSatelliteModemStateChanged(msg); 898 break; 899 } 900 // Ignore all unexpected events. 901 return HANDLED; 902 } 903 handleSatelliteEnabledStateChanged(boolean on)904 private void handleSatelliteEnabledStateChanged(boolean on) { 905 if (on) { 906 /* Framework received a disable request when the enable request was in progress. 907 * We need to set the previous state to NOT_CONNECTED since the enable has 908 * succeeded so that when disable fail, we can move to NOT_CONNECTED state properly. 909 */ 910 mPreviousState = SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED; 911 plogd("Enable request has succeeded. Set mPreviousState to NOT_CONNECTED"); 912 } else { 913 transitionTo(mPowerOffState); 914 } 915 } 916 handleEventSatelliteModemStateChanged(@onNull Message msg)917 private void handleEventSatelliteModemStateChanged(@NonNull Message msg) { 918 int state = msg.arg1; 919 if (state == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED) { 920 mPreviousState = state; 921 } else if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) { 922 plogd("Modem OFF state will be processed after getting the confirmation of the" 923 + " disable request"); 924 deferMessage(msg); 925 } 926 } 927 } 928 929 private class IdleState extends State { 930 @Override enter()931 public void enter() { 932 if (DBG) plogd("Entering IdleState"); 933 mPreviousState = mCurrentState; 934 mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_IDLE; 935 mIsSendingTriggeredDuringTransferringState.set(false); 936 stopNbIotInactivityTimer(); 937 938 //Enable Cellular Modem scanning 939 boolean configSatelliteAllowTnScanningDuringSatelliteSession = 940 isTnScanningAllowedDuringSatelliteSession(); 941 if (configSatelliteAllowTnScanningDuringSatelliteSession) { 942 Message onCompleted = 943 obtainMessage(EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE); 944 mSatelliteModemInterface 945 .enableCellularModemWhileSatelliteModeIsOn(true, onCompleted); 946 } else { 947 plogd("Device does not allow cellular modem scanning"); 948 } 949 if (isConcurrentTnScanningSupported() 950 || !configSatelliteAllowTnScanningDuringSatelliteSession) { 951 plogd("IDLE state is hidden from clients"); 952 } else { 953 notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_IDLE); 954 } 955 } 956 957 @Override processMessage(Message msg)958 public boolean processMessage(Message msg) { 959 if (DBG) plogd("IdleState: processing " + getWhatToString(msg.what)); 960 switch (msg.what) { 961 case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED: 962 handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj); 963 break; 964 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 965 handleSatelliteEnabledStateChanged(!(boolean) msg.obj, "IdleState"); 966 break; 967 case EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE: 968 handleEventDisableCellularModemWhileSatelliteModeIsOnDone( 969 (AsyncResult) msg.obj); 970 break; 971 case EVENT_SATELLITE_ENABLEMENT_STARTED: 972 handleSatelliteEnablementStarted((boolean) msg.obj); 973 break; 974 case EVENT_SCREEN_STATE_CHANGED: 975 handleEventScreenStateChanged((AsyncResult) msg.obj); 976 break; 977 case EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT: 978 handleEventScreenOffInactivityTimerTimedOut(); 979 break; 980 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 981 handleSatelliteModemStateChanged(msg); 982 break; 983 case EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE: 984 plogd("EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE"); 985 break; 986 case EVENT_SERVICE_STATE_CHANGED: 987 if (!mIgnoreCellularServiceState) { 988 AsyncResult ar = (msg.obj != null) ? (AsyncResult) msg.obj : null; 989 if (ar == null || ar.result == null) { 990 plogd("IdleState: processing: can't access ServiceState"); 991 } else { 992 ServiceState newServiceState = (ServiceState) ar.result; 993 handleEventServiceStateChanged(newServiceState); 994 } 995 } else { 996 plogd("IdleState: processing: ignore EVENT_SERVICE_STATE_CHANGED"); 997 } 998 break; 999 } 1000 // Ignore all unexpected events. 1001 return HANDLED; 1002 } 1003 handleEventDatagramTransferStateChanged( @onNull DatagramTransferState datagramTransferState)1004 private void handleEventDatagramTransferStateChanged( 1005 @NonNull DatagramTransferState datagramTransferState) { 1006 if ((datagramTransferState.sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING) 1007 || (datagramTransferState.receiveState 1008 == SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING)) { 1009 transitionTo(mTransferringState); 1010 } else if ((datagramTransferState.sendState 1011 == SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT) 1012 || (datagramTransferState.receiveState 1013 == SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT)) { 1014 if (mSatelliteController.isSatelliteAttachRequired()) { 1015 transitionTo(mNotConnectedState); 1016 } else { 1017 ploge("Unexpected transferring state received for non-NB-IOT NTN"); 1018 } 1019 } 1020 } 1021 handleEventServiceStateChanged(ServiceState serviceState)1022 private void handleEventServiceStateChanged(ServiceState serviceState) { 1023 boolean isInServiceOrEmergency = 1024 serviceState.getVoiceRegState() == ServiceState.STATE_IN_SERVICE 1025 || serviceState.getDataRegState() == ServiceState.STATE_IN_SERVICE 1026 || serviceState.isEmergencyOnly(); 1027 if (!isInServiceOrEmergency) { 1028 plogd("handleEventServiceStateChanged: is not IN_SERVICE or EMERGENCY_ONLY"); 1029 return; 1030 } 1031 1032 // In emergency 1033 boolean isEmergency = mSatelliteController.getRequestIsEmergency(); 1034 if (isEmergency) { 1035 boolean isEmergencyCommunicationEstablished = (mDatagramController == null) 1036 ? false : mDatagramController.isEmergencyCommunicationEstablished(); 1037 boolean isTurnOffAllowed = 1038 mSatelliteController.turnOffSatelliteSessionForEmergencyCall(getSubId()); 1039 if (isEmergencyCommunicationEstablished || !isTurnOffAllowed) { 1040 logd("handleEventServiceStateChanged: " 1041 + "can't disable emergency satellite session"); 1042 return; 1043 } 1044 } 1045 1046 mSatelliteController.requestSatelliteEnabled( 1047 false /*enableSatellite*/, 1048 false /*enableDemoMode*/, 1049 isEmergency /*isEmergency*/, 1050 new IIntegerConsumer.Stub() { 1051 @Override 1052 public void accept(int result) { 1053 plogd("requestSatelliteEnabled result=" + result); 1054 if (result == SatelliteManager.SATELLITE_RESULT_SUCCESS) { 1055 mSessionMetricsStats.addCountOfAutoExitDueToTnNetwork(); 1056 } 1057 } 1058 }); 1059 } 1060 handleEventDisableCellularModemWhileSatelliteModeIsOnDone( @onNull AsyncResult result)1061 private void handleEventDisableCellularModemWhileSatelliteModeIsOnDone( 1062 @NonNull AsyncResult result) { 1063 int error = SatelliteServiceUtils.getSatelliteError( 1064 result, "DisableCellularModemWhileSatelliteModeIsOnDone"); 1065 plogd("Disable TN scanning done with result: " + error); 1066 } 1067 handleSatelliteModemStateChanged(@onNull Message msg)1068 private void handleSatelliteModemStateChanged(@NonNull Message msg) { 1069 int state = msg.arg1; 1070 if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) { 1071 transitionTo(mPowerOffState); 1072 } else if (state == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED 1073 || state == SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED) { 1074 if (isConcurrentTnScanningSupported()) { 1075 plogd("Notifying the new state " + state + " to clients but still" 1076 + " stay at IDLE state internally"); 1077 notifyStateChangedEvent(state); 1078 } else { 1079 plogd("Ignoring the modem state " + state); 1080 } 1081 } 1082 } 1083 1084 @Override exit()1085 public void exit() { 1086 if (DBG) plogd("Exiting IdleState"); 1087 // Disable cellular modem scanning 1088 mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(false, null); 1089 } 1090 } 1091 1092 private class TransferringState extends State { 1093 @Override enter()1094 public void enter() { 1095 if (DBG) plogd("Entering TransferringState"); 1096 stopNbIotInactivityTimer(); 1097 stopEsosInactivityTimer(); 1098 stopP2pSmsInactivityTimer(); 1099 1100 mPreviousState = mCurrentState; 1101 mCurrentState = SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING; 1102 notifyStateChangedEvent(SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING); 1103 } 1104 1105 @Override processMessage(Message msg)1106 public boolean processMessage(Message msg) { 1107 if (DBG) plogd("TransferringState: processing " + getWhatToString(msg.what)); 1108 switch (msg.what) { 1109 case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED: 1110 handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj); 1111 return HANDLED; 1112 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 1113 handleSatelliteEnabledStateChanged(!(boolean) msg.obj, "TransferringState"); 1114 break; 1115 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 1116 handleEventSatelliteModemStateChange(msg.arg1); 1117 break; 1118 case EVENT_SATELLITE_ENABLEMENT_STARTED: 1119 handleSatelliteEnablementStarted((boolean) msg.obj); 1120 break; 1121 case EVENT_SCREEN_STATE_CHANGED: 1122 handleEventScreenStateChanged((AsyncResult) msg.obj); 1123 break; 1124 case EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT: 1125 handleEventScreenOffInactivityTimerTimedOut(); 1126 break; 1127 } 1128 // Ignore all unexpected events. 1129 return HANDLED; 1130 } 1131 handleEventDatagramTransferStateChanged( @onNull DatagramTransferState datagramTransferState)1132 private void handleEventDatagramTransferStateChanged( 1133 @NonNull DatagramTransferState datagramTransferState) { 1134 if (isSending(datagramTransferState.sendState) || isReceiving( 1135 datagramTransferState.receiveState)) { 1136 // Stay at transferring state. 1137 } else { 1138 if (mSatelliteController.isSatelliteAttachRequired()) { 1139 transitionTo(mConnectedState); 1140 } else { 1141 if ((datagramTransferState.sendState 1142 == SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED) 1143 || (datagramTransferState.receiveState 1144 == SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED)) { 1145 transitionTo(mIdleState); 1146 } else { 1147 transitionTo(mListeningState); 1148 } 1149 } 1150 } 1151 } 1152 handleEventSatelliteModemStateChange( @atelliteManager.SatelliteModemState int state)1153 private void handleEventSatelliteModemStateChange( 1154 @SatelliteManager.SatelliteModemState int state) { 1155 if (state == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED) { 1156 transitionTo(mNotConnectedState); 1157 } else if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) { 1158 transitionTo(mPowerOffState); 1159 } 1160 } 1161 } 1162 1163 private class ListeningState extends State { 1164 @Override enter()1165 public void enter() { 1166 if (DBG) plogd("Entering ListeningState"); 1167 1168 mPreviousState = mCurrentState; 1169 mCurrentState = SATELLITE_MODEM_STATE_LISTENING; 1170 long timeoutMillis = updateListeningMode(true); 1171 sendMessageDelayed(EVENT_LISTENING_TIMER_TIMEOUT, timeoutMillis); 1172 mIsSendingTriggeredDuringTransferringState.set(false); 1173 notifyStateChangedEvent(SATELLITE_MODEM_STATE_LISTENING); 1174 } 1175 1176 @Override exit()1177 public void exit() { 1178 if (DBG) plogd("Exiting ListeningState"); 1179 1180 removeMessages(EVENT_LISTENING_TIMER_TIMEOUT); 1181 updateListeningMode(false); 1182 } 1183 1184 @Override processMessage(Message msg)1185 public boolean processMessage(Message msg) { 1186 if (DBG) plogd("ListeningState: processing " + getWhatToString(msg.what)); 1187 switch (msg.what) { 1188 case EVENT_LISTENING_TIMER_TIMEOUT: 1189 transitionTo(mIdleState); 1190 break; 1191 case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED: 1192 handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj); 1193 break; 1194 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 1195 handleSatelliteEnabledStateChanged(!(boolean) msg.obj, "ListeningState"); 1196 break; 1197 case EVENT_SATELLITE_ENABLEMENT_STARTED: 1198 handleSatelliteEnablementStarted((boolean) msg.obj); 1199 break; 1200 case EVENT_SCREEN_STATE_CHANGED: 1201 handleEventScreenStateChanged((AsyncResult) msg.obj); 1202 break; 1203 case EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT: 1204 handleEventScreenOffInactivityTimerTimedOut(); 1205 break; 1206 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 1207 handleEventSatelliteModemStateChange(msg); 1208 break; 1209 } 1210 // Ignore all unexpected events. 1211 return HANDLED; 1212 } 1213 updateListeningMode(boolean enabled)1214 private long updateListeningMode(boolean enabled) { 1215 long timeoutMillis; 1216 if (mIsSendingTriggeredDuringTransferringState.get()) { 1217 timeoutMillis = mSatelliteStayAtListeningFromSendingMillis; 1218 } else { 1219 timeoutMillis = mSatelliteStayAtListeningFromReceivingMillis; 1220 } 1221 mSatelliteModemInterface.requestSatelliteListeningEnabled( 1222 enabled, (int) timeoutMillis, null); 1223 return timeoutMillis; 1224 } 1225 handleEventDatagramTransferStateChanged( @onNull DatagramTransferState datagramTransferState)1226 private void handleEventDatagramTransferStateChanged( 1227 @NonNull DatagramTransferState datagramTransferState) { 1228 if (datagramTransferState.sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING 1229 || datagramTransferState.receiveState 1230 == SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING) { 1231 transitionTo(mTransferringState); 1232 } 1233 } 1234 handleEventSatelliteModemStateChange(@onNull Message msg)1235 private void handleEventSatelliteModemStateChange(@NonNull Message msg) { 1236 int state = msg.arg1; 1237 if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) { 1238 transitionTo(mPowerOffState); 1239 } 1240 } 1241 } 1242 1243 private class NotConnectedState extends State { 1244 @Override enter()1245 public void enter() { 1246 if (DBG) plogd("Entering NotConnectedState"); 1247 1248 mPreviousState = mCurrentState; 1249 mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED; 1250 notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED); 1251 startNbIotInactivityTimer(); 1252 evaluateStartingEsosInactivityTimer(); 1253 evaluateStartingP2pSmsInactivityTimer(); 1254 } 1255 1256 @Override exit()1257 public void exit() { 1258 if (DBG) plogd("Exiting NotConnectedState"); 1259 } 1260 1261 @Override processMessage(Message msg)1262 public boolean processMessage(Message msg) { 1263 if (DBG) plogd("NotConnectedState: processing " + getWhatToString(msg.what)); 1264 switch (msg.what) { 1265 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 1266 handleSatelliteEnabledStateChanged( 1267 !(boolean) msg.obj, "NotConnectedState"); 1268 break; 1269 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 1270 handleEventSatelliteModemStateChanged(msg.arg1); 1271 break; 1272 case EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT: 1273 if (isP2pSmsInActivityTimerStarted()) { 1274 plogd("NotConnectedState: processing: P2P_SMS inactivity timer running " 1275 + "can not move to IDLE"); 1276 } else { 1277 transitionTo(mIdleState); 1278 } 1279 break; 1280 case EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT: 1281 handleEventP2pSmsInactivityTimerTimedOut(); 1282 break; 1283 case EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT: 1284 transitionTo(mIdleState); 1285 break; 1286 case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED: 1287 handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj); 1288 break; 1289 case EVENT_SATELLITE_ENABLEMENT_STARTED: 1290 handleSatelliteEnablementStarted((boolean) msg.obj); 1291 break; 1292 case EVENT_SCREEN_STATE_CHANGED: 1293 handleEventScreenStateChanged((AsyncResult) msg.obj); 1294 break; 1295 case EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT: 1296 handleEventScreenOffInactivityTimerTimedOut(); 1297 break; 1298 } 1299 // Ignore all unexpected events. 1300 return HANDLED; 1301 } 1302 handleEventSatelliteModemStateChanged( @atelliteManager.SatelliteModemState int state)1303 private void handleEventSatelliteModemStateChanged( 1304 @SatelliteManager.SatelliteModemState int state) { 1305 if (state == SATELLITE_MODEM_STATE_CONNECTED) { 1306 transitionTo(mConnectedState); 1307 } else if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) { 1308 transitionTo(mPowerOffState); 1309 } 1310 } 1311 handleEventDatagramTransferStateChanged( @onNull DatagramTransferState datagramTransferState)1312 private void handleEventDatagramTransferStateChanged( 1313 @NonNull DatagramTransferState datagramTransferState) { 1314 if (datagramTransferState.sendState 1315 == SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT 1316 || datagramTransferState.receiveState 1317 == SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT) { 1318 stopNbIotInactivityTimer(); 1319 1320 if (mSatelliteController.getRequestIsEmergency()) { 1321 stopEsosInactivityTimer(); 1322 } 1323 stopP2pSmsInactivityTimer(); 1324 } else if (datagramTransferState.sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE 1325 && datagramTransferState.receiveState 1326 == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE) { 1327 startNbIotInactivityTimer(); 1328 evaluateStartingEsosInactivityTimer(); 1329 evaluateStartingP2pSmsInactivityTimer(); 1330 } else if (isSending(datagramTransferState.sendState) 1331 || isReceiving(datagramTransferState.receiveState)) { 1332 stopNbIotInactivityTimer(); 1333 1334 int datagramType = datagramTransferState.datagramType; 1335 if (datagramType == DATAGRAM_TYPE_SOS_MESSAGE) { 1336 stopEsosInactivityTimer(); 1337 } else if (datagramType == DATAGRAM_TYPE_SMS) { 1338 stopP2pSmsInactivityTimer(); 1339 } else { 1340 plogd("datagram type is not SOS_Message and SMS " + datagramType); 1341 } 1342 } 1343 } 1344 } 1345 1346 private class ConnectedState extends State { 1347 @Override enter()1348 public void enter() { 1349 if (DBG) plogd("Entering ConnectedState"); 1350 1351 mPreviousState = mCurrentState; 1352 mCurrentState = SATELLITE_MODEM_STATE_CONNECTED; 1353 notifyStateChangedEvent(SATELLITE_MODEM_STATE_CONNECTED); 1354 startNbIotInactivityTimer(); 1355 evaluateStartingEsosInactivityTimer(); 1356 evaluateStartingP2pSmsInactivityTimer(); 1357 mSatelliteController.updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify( 1358 mSatelliteController.getSatellitePhone()); 1359 } 1360 1361 @Override exit()1362 public void exit() { 1363 if (DBG) plogd("Exiting ConnectedState"); 1364 } 1365 1366 @Override processMessage(Message msg)1367 public boolean processMessage(Message msg) { 1368 if (DBG) plogd("ConnectedState: processing " + getWhatToString(msg.what)); 1369 switch (msg.what) { 1370 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 1371 handleSatelliteEnabledStateChanged( 1372 !(boolean) msg.obj, "ConnectedState"); 1373 break; 1374 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 1375 handleEventSatelliteModemStateChanged(msg.arg1); 1376 break; 1377 case EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT: 1378 transitionTo(mIdleState); 1379 break; 1380 case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED: 1381 handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj); 1382 break; 1383 case EVENT_SATELLITE_ENABLEMENT_STARTED: 1384 handleSatelliteEnablementStarted((boolean) msg.obj); 1385 break; 1386 case EVENT_SCREEN_STATE_CHANGED: 1387 handleEventScreenStateChanged((AsyncResult) msg.obj); 1388 break; 1389 case EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT: 1390 handleEventScreenOffInactivityTimerTimedOut(); 1391 break; 1392 case EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT: 1393 if (isP2pSmsInActivityTimerStarted()) { 1394 plogd("ConnectedState: processing: P2P_SMS inactivity timer running " 1395 + "can not move to IDLE"); 1396 } else { 1397 transitionTo(mIdleState); 1398 } 1399 break; 1400 case EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT: 1401 handleEventP2pSmsInactivityTimerTimedOut(); 1402 break; 1403 } 1404 // Ignore all unexpected events. 1405 return HANDLED; 1406 } 1407 handleEventSatelliteModemStateChanged( @atelliteManager.SatelliteModemState int state)1408 private void handleEventSatelliteModemStateChanged( 1409 @SatelliteManager.SatelliteModemState int state) { 1410 if (state == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED) { 1411 transitionTo(mNotConnectedState); 1412 } else if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) { 1413 transitionTo(mPowerOffState); 1414 } 1415 } 1416 handleEventDatagramTransferStateChanged( @onNull DatagramTransferState datagramTransferState)1417 private void handleEventDatagramTransferStateChanged( 1418 @NonNull DatagramTransferState datagramTransferState) { 1419 if (isSending(datagramTransferState.sendState) 1420 || isReceiving(datagramTransferState.receiveState)) { 1421 transitionTo(mTransferringState); 1422 } 1423 } 1424 } 1425 1426 /** 1427 * @return the string for msg.what 1428 */ 1429 @Override getWhatToString(int what)1430 protected String getWhatToString(int what) { 1431 String whatString; 1432 switch (what) { 1433 case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED: 1434 whatString = "EVENT_DATAGRAM_TRANSFER_STATE_CHANGED"; 1435 break; 1436 case EVENT_LISTENING_TIMER_TIMEOUT: 1437 whatString = "EVENT_LISTENING_TIMER_TIMEOUT"; 1438 break; 1439 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 1440 whatString = "EVENT_SATELLITE_ENABLED_STATE_CHANGED"; 1441 break; 1442 case EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE: 1443 whatString = "EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE"; 1444 break; 1445 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 1446 whatString = "EVENT_SATELLITE_MODEM_STATE_CHANGED"; 1447 break; 1448 case EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT: 1449 whatString = "EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT"; 1450 break; 1451 case EVENT_SATELLITE_ENABLEMENT_STARTED: 1452 whatString = "EVENT_SATELLITE_ENABLEMENT_STARTED"; 1453 break; 1454 case EVENT_SATELLITE_ENABLEMENT_FAILED: 1455 whatString = "EVENT_SATELLITE_ENABLEMENT_FAILED"; 1456 break; 1457 case EVENT_SCREEN_STATE_CHANGED: 1458 whatString = "EVENT_SCREEN_STATE_CHANGED"; 1459 break; 1460 case EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT: 1461 whatString = "EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT"; 1462 break; 1463 case EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT: 1464 whatString = "EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT"; 1465 break; 1466 case EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT: 1467 whatString = "EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT"; 1468 break; 1469 case EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE: 1470 whatString = "EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE"; 1471 break; 1472 case EVENT_SERVICE_STATE_CHANGED: 1473 whatString = "EVENT_SERVICE_STATE_CHANGED"; 1474 break; 1475 default: 1476 whatString = "UNKNOWN EVENT " + what; 1477 } 1478 return whatString; 1479 } 1480 setInitialState(boolean isSatelliteSupported)1481 private void setInitialState(boolean isSatelliteSupported) { 1482 if (isSatelliteSupported) { 1483 setInitialState(mPowerOffState); 1484 } else { 1485 setInitialState(mUnavailableState); 1486 } 1487 } 1488 getSubId()1489 private int getSubId() { 1490 return mSatelliteController.getSelectedSatelliteSubId(); 1491 } 1492 notifyStateChangedEvent(@atelliteManager.SatelliteModemState int state)1493 private void notifyStateChangedEvent(@SatelliteManager.SatelliteModemState int state) { 1494 mDatagramController.onSatelliteModemStateChanged(state); 1495 1496 List<ISatelliteModemStateCallback> toBeRemoved = new ArrayList<>(); 1497 mListeners.values().forEach(listener -> { 1498 try { 1499 listener.onSatelliteModemStateChanged(state); 1500 } catch (RemoteException e) { 1501 plogd("notifyStateChangedEvent RemoteException: " + e); 1502 toBeRemoved.add(listener); 1503 } 1504 }); 1505 1506 toBeRemoved.forEach(listener -> { 1507 mListeners.remove(listener.asBinder()); 1508 }); 1509 } 1510 handleSatelliteEnabledStateChanged(boolean off, String caller)1511 private void handleSatelliteEnabledStateChanged(boolean off, String caller) { 1512 if (off) { 1513 transitionTo(mPowerOffState); 1514 } else { 1515 ploge(caller + ": Unexpected satellite radio powered-on state changed event"); 1516 } 1517 } 1518 isSending(@atelliteManager.SatelliteDatagramTransferState int sendState)1519 private boolean isSending(@SatelliteManager.SatelliteDatagramTransferState int sendState) { 1520 return (sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING 1521 || sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS); 1522 } 1523 isReceiving(@atelliteManager.SatelliteDatagramTransferState int receiveState)1524 private boolean isReceiving(@SatelliteManager.SatelliteDatagramTransferState int receiveState) { 1525 return (receiveState == SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING 1526 || receiveState == SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS 1527 || receiveState == SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE); 1528 } 1529 1530 @NonNull getSatelliteGatewayPackageName()1531 private String getSatelliteGatewayPackageName() { 1532 if (!TextUtils.isEmpty(mSatelliteGatewayServicePackageName)) { 1533 return mSatelliteGatewayServicePackageName; 1534 } 1535 return TextUtils.emptyIfNull(mContext.getResources().getString( 1536 R.string.config_satellite_gateway_service_package)); 1537 } 1538 bindService()1539 private void bindService() { 1540 synchronized (mLock) { 1541 if (mIsBinding || mIsBound) return; 1542 mIsBinding = true; 1543 } 1544 mExponentialBackoff.start(); 1545 1546 String packageName = getSatelliteGatewayPackageName(); 1547 if (TextUtils.isEmpty(packageName)) { 1548 ploge("Unable to bind to the satellite gateway service because the package is" 1549 + " undefined."); 1550 // Since the package name comes from static device configs, stop retry because 1551 // rebind will continue to fail without a valid package name. 1552 synchronized (mLock) { 1553 mIsBinding = false; 1554 } 1555 mExponentialBackoff.stop(); 1556 return; 1557 } 1558 Intent intent = new Intent(SatelliteGatewayService.SERVICE_INTERFACE); 1559 intent.setPackage(packageName); 1560 1561 mSatelliteGatewayServiceConnection = new SatelliteGatewayServiceConnection(); 1562 try { 1563 boolean success = mContext.bindService( 1564 intent, mSatelliteGatewayServiceConnection, Context.BIND_AUTO_CREATE); 1565 if (success) { 1566 plogd("Successfully bound to the satellite gateway service."); 1567 } else { 1568 synchronized (mLock) { 1569 mIsBinding = false; 1570 } 1571 mExponentialBackoff.notifyFailed(); 1572 ploge("Error binding to the satellite gateway service. Retrying in " 1573 + mExponentialBackoff.getCurrentDelay() + " ms."); 1574 } 1575 } catch (Exception e) { 1576 synchronized (mLock) { 1577 mIsBinding = false; 1578 } 1579 mExponentialBackoff.notifyFailed(); 1580 ploge("Exception binding to the satellite gateway service. Retrying in " 1581 + mExponentialBackoff.getCurrentDelay() + " ms. Exception: " + e); 1582 } 1583 } 1584 unbindService()1585 private void unbindService() { 1586 plogd("unbindService"); 1587 mExponentialBackoff.stop(); 1588 mSatelliteGatewayService = null; 1589 synchronized (mLock) { 1590 mIsBinding = false; 1591 mIsBound = false; 1592 } 1593 if (mSatelliteGatewayServiceConnection != null) { 1594 mContext.unbindService(mSatelliteGatewayServiceConnection); 1595 mSatelliteGatewayServiceConnection = null; 1596 } 1597 } 1598 1599 private class SatelliteGatewayServiceConnection implements ServiceConnection { 1600 @Override onServiceConnected(ComponentName name, IBinder service)1601 public void onServiceConnected(ComponentName name, IBinder service) { 1602 plogd("onServiceConnected: ComponentName=" + name); 1603 synchronized (mLock) { 1604 mIsBound = true; 1605 mIsBinding = false; 1606 } 1607 mSatelliteGatewayService = ISatelliteGateway.Stub.asInterface(service); 1608 mExponentialBackoff.stop(); 1609 } 1610 1611 @Override onServiceDisconnected(ComponentName name)1612 public void onServiceDisconnected(ComponentName name) { 1613 ploge("onServiceDisconnected: Waiting for reconnect."); 1614 synchronized (mLock) { 1615 mIsBinding = false; 1616 mIsBound = false; 1617 } 1618 mSatelliteGatewayService = null; 1619 } 1620 1621 @Override onBindingDied(ComponentName name)1622 public void onBindingDied(ComponentName name) { 1623 ploge("onBindingDied: Unbinding and rebinding service."); 1624 synchronized (mLock) { 1625 mIsBound = false; 1626 mIsBinding = false; 1627 } 1628 unbindService(); 1629 mExponentialBackoff.start(); 1630 } 1631 } 1632 handleSatelliteEnablementStarted(boolean enabled)1633 private void handleSatelliteEnablementStarted(boolean enabled) { 1634 if (!enabled) { 1635 transitionTo(mDisablingState); 1636 } 1637 } 1638 registerForScreenStateChanged()1639 private void registerForScreenStateChanged() { 1640 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 1641 Rlog.d(TAG, "registerForScreenStateChanged: carrierRoamingNbIotNtn is disabled"); 1642 return; 1643 } 1644 1645 if (!mIsRegisteredScreenStateChanged && mDeviceStateMonitor != null) { 1646 mDeviceStateMonitor.registerForScreenStateChanged( 1647 getHandler(), EVENT_SCREEN_STATE_CHANGED, null); 1648 1649 mIsRegisteredScreenStateChanged = true; 1650 plogd("registerForScreenStateChanged: registered"); 1651 } else { 1652 plogw("registerForScreenStateChanged: skip register, mIsRegisteredScreenStateChanged=" 1653 + mIsRegisteredScreenStateChanged + "," 1654 + " mDeviceStateMonitor=" + (mDeviceStateMonitor != null)); 1655 } 1656 } 1657 unregisterForScreenStateChanged()1658 private void unregisterForScreenStateChanged() { 1659 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 1660 Rlog.d(TAG, "unregisterForScreenStateChanged: carrierRoamingNbIotNtn is disabled"); 1661 return; 1662 } 1663 1664 if (mIsRegisteredScreenStateChanged && mDeviceStateMonitor != null) { 1665 mDeviceStateMonitor.unregisterForScreenStateChanged(getHandler()); 1666 removeMessages(EVENT_SCREEN_STATE_CHANGED); 1667 removeMessages(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT); 1668 1669 removeDeferredMessages(EVENT_SCREEN_STATE_CHANGED); 1670 removeDeferredMessages(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT); 1671 1672 mIsRegisteredScreenStateChanged = false; 1673 plogd("unregisterForScreenStateChanged: unregistered"); 1674 } 1675 } 1676 handleEventScreenStateChanged(AsyncResult asyncResult)1677 private void handleEventScreenStateChanged(AsyncResult asyncResult) { 1678 if (asyncResult == null) { 1679 ploge("handleEventScreenStateChanged: asyncResult is null"); 1680 return; 1681 } 1682 1683 boolean screenOn = (boolean) asyncResult.result; 1684 if (mIsScreenOn == screenOn) { 1685 if (DBG) plogd("handleEventScreenStateChanged: screen state is not changed"); 1686 return; 1687 } 1688 mIsScreenOn = screenOn; 1689 1690 if (!mSatelliteController.isInCarrierRoamingNbIotNtn()) { 1691 logd("handleEventScreenStateChanged: device is not in CarrierRoamingNbIotNtn"); 1692 return; 1693 } 1694 1695 if (mSatelliteController.getRequestIsEmergency()) { 1696 if (DBG) logd("handleEventScreenStateChanged: Emergency mode"); 1697 // This is for coexistence 1698 // emergency mode can be set after registerForScreenStateChanged() called for P2P-sms 1699 return; 1700 } 1701 1702 int subId = getSubId(); 1703 if (!isP2pSmsSupportedOnCarrierRoamingNtn(subId)) { 1704 if (DBG) plogd("handleEventScreenStateChanged: P2P_SMS is not supported"); 1705 return; 1706 } 1707 1708 if (!screenOn) { 1709 // Screen off, start timer 1710 int timeoutMillis = getScreenOffInactivityTimeoutDurationSec() * 1000; 1711 1712 if (mAlarmManager == null) { 1713 plogd("handleEventScreenStateChanged: can not access AlarmManager to start timer"); 1714 return; 1715 } 1716 1717 mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1718 SystemClock.elapsedRealtime() + timeoutMillis, 1719 TAG, new HandlerExecutor(getHandler()), new WorkSource(), mAlarmListener); 1720 plogd("handleEventScreenStateChanged: start timer " + timeoutMillis); 1721 } else { 1722 // Screen on, stop timer 1723 removeMessages(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT); 1724 1725 if (mAlarmManager == null) { 1726 plogd("handleEventScreenStateChanged: can not access AlarmManager to stop timer"); 1727 return; 1728 } 1729 1730 mAlarmManager.cancel(mAlarmListener); 1731 plogd("handleEventScreenStateChanged: stop timer"); 1732 } 1733 } 1734 handleEventP2pSmsInactivityTimerTimedOut()1735 private void handleEventP2pSmsInactivityTimerTimedOut() { 1736 if (isEsosInActivityTimerStarted()) { 1737 plogd("handleEventP2pSmsInactivityTimerTimedOut: processing: ESOS inactivity timer " 1738 + "running can not move to IDLE"); 1739 } else { 1740 if (isTnScanningAllowedDuringSatelliteSession()) { 1741 plogd("handleEventP2pSmsInactivityTimerTimedOut: Transition to IDLE state"); 1742 transitionTo(mIdleState); 1743 } else { 1744 if (mSatelliteController.getRequestIsEmergency()) { 1745 plogd("handleEventP2pSmsInactivityTimerTimedOut: Emergency mode"); 1746 return; 1747 } 1748 1749 plogd("handleEventP2pSmsInactivityTimerTimedOut: request disable satellite"); 1750 mSatelliteController.requestSatelliteEnabled( 1751 false /*enableSatellite*/, 1752 false /*enableDemoMode*/, 1753 mSatelliteController.getRequestIsEmergency() /*isEmergency*/, 1754 new IIntegerConsumer.Stub() { 1755 @Override 1756 public void accept(int result) { 1757 plogd("requestSatelliteEnabled result=" + result); 1758 } 1759 }); 1760 } 1761 } 1762 } 1763 getScreenOffInactivityTimeoutDurationSec()1764 private int getScreenOffInactivityTimeoutDurationSec() { 1765 PersistableBundle config = mSatelliteController.getPersistableBundle(getSubId()); 1766 1767 return config.getInt(KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT, 1768 DEFAULT_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC); 1769 } 1770 getEsosInactivityTimeoutDurationSec()1771 private int getEsosInactivityTimeoutDurationSec() { 1772 PersistableBundle config = mSatelliteController.getPersistableBundle(getSubId()); 1773 1774 return config.getInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT, 1775 DEFAULT_ESOS_INACTIVITY_TIMEOUT_SEC); 1776 } 1777 evaluateStartingEsosInactivityTimer()1778 private void evaluateStartingEsosInactivityTimer() { 1779 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 1780 plogd("evaluateStartingEsosInactivityTimer: " 1781 + "carrierRoamingNbIotNtn is disabled"); 1782 return; 1783 } 1784 1785 if (isEsosInActivityTimerStarted()) { 1786 plogd("isEsosInActivityTimerStarted: " 1787 + "ESOS inactivity timer already started"); 1788 return; 1789 } 1790 1791 int subId = getSubId(); 1792 if (!mSatelliteController.isSatelliteEsosSupported(subId)) { 1793 plogd("evaluateStartingEsosInactivityTimer: ESOS is not supported"); 1794 return; 1795 } 1796 1797 if (!mSatelliteController.getRequestIsEmergency()) { 1798 plogd("evaluateStartingEsosInactivityTimer: request is not emergency"); 1799 return; 1800 } 1801 1802 if (mIsDeviceAlignedWithSatellite) { 1803 plogd("evaluateStartingEsosInactivityTimer: " 1804 + "can't start ESOS inactivity timer due to device aligned satellite"); 1805 return; 1806 } 1807 1808 int timeOutMillis = getEsosInactivityTimeoutDurationSec() * 1000; 1809 DatagramController datagramController = DatagramController.getInstance(); 1810 if (datagramController.isSendingInIdleState() 1811 && datagramController.isPollingInIdleState()) { 1812 sendMessageDelayed(EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT, timeOutMillis); 1813 plogd("evaluateStartingEsosInactivityTimer: start ESOS inactivity timer " 1814 + timeOutMillis); 1815 } else { 1816 plogd("evaluateStartingEsosInactivityTimer: " 1817 + "can't start ESOS inactivity timer"); 1818 } 1819 } 1820 stopEsosInactivityTimer()1821 private void stopEsosInactivityTimer() { 1822 if (isEsosInActivityTimerStarted()) { 1823 removeMessages(EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT); 1824 plogd("stopEsosInactivityTimer: ESOS inactivity timer stopped"); 1825 } 1826 } 1827 1828 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) isEsosInActivityTimerStarted()1829 public boolean isEsosInActivityTimerStarted() { 1830 return hasMessages(EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT); 1831 } 1832 getP2pSmsInactivityTimeoutDurationSec()1833 private int getP2pSmsInactivityTimeoutDurationSec() { 1834 PersistableBundle config = mSatelliteController.getPersistableBundle(getSubId()); 1835 1836 return config.getInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT, 1837 DEFAULT_P2P_SMS_INACTIVITY_TIMEOUT_SEC); 1838 } 1839 evaluateStartingP2pSmsInactivityTimer()1840 private void evaluateStartingP2pSmsInactivityTimer() { 1841 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 1842 plogd("evaluateStartingP2pSmsInactivityTimer: " 1843 + "carrierRoamingNbIotNtn is disabled"); 1844 return; 1845 } 1846 1847 if (isP2pSmsInActivityTimerStarted()) { 1848 plogd("isP2pSmsInActivityTimerStarted: " 1849 + "P2P_SMS inactivity timer already started"); 1850 return; 1851 } 1852 1853 int subId = getSubId(); 1854 if (!isP2pSmsSupportedOnCarrierRoamingNtn(subId)) { 1855 if (DBG) plogd("evaluateStartingP2pSmsInactivityTimer: P2P_SMS is not supported"); 1856 return; 1857 } 1858 1859 if (mIsDeviceAlignedWithSatellite) { 1860 plogd("evaluateStartingP2pSmsInactivityTimer: " 1861 + "can't start P2P_SMS inactivity timer due to device aligned satellite"); 1862 return; 1863 } 1864 1865 int timeOutMillis = getP2pSmsInactivityTimeoutDurationSec() * 1000; 1866 DatagramController datagramController = DatagramController.getInstance(); 1867 if (datagramController.isSendingInIdleState() 1868 && datagramController.isPollingInIdleState()) { 1869 sendMessageDelayed(EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT, timeOutMillis); 1870 plogd("evaluateStartingP2pSmsInactivityTimer: start P2P_SMS inactivity timer " 1871 + timeOutMillis); 1872 } else { 1873 plogd("evaluateStartingP2pSmsInactivityTimer: " 1874 + "can't start P2P_SMS inactivity timer"); 1875 } 1876 } 1877 stopP2pSmsInactivityTimer()1878 private void stopP2pSmsInactivityTimer() { 1879 if (isP2pSmsInActivityTimerStarted()) { 1880 removeMessages(EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT); 1881 plogd("stopP2pSmsInactivityTimer: P2P_SMS inactivity timer stopped"); 1882 } 1883 } 1884 1885 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) isP2pSmsInActivityTimerStarted()1886 public boolean isP2pSmsInActivityTimerStarted() { 1887 return hasMessages(EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT); 1888 } 1889 1890 /** 1891 * Initializes the inactivity start timestamp. 1892 * 1893 * <p>This method is called when 1) the datagram transfer state changes to idle or 2) the 1894 * device is unaligned with the satellite. 1895 */ checkForInactivity()1896 private void checkForInactivity() { 1897 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 1898 return; 1899 } 1900 1901 // If the inactivity start timestamp is not undefined, it means the inactivity has already 1902 // started. 1903 if (mInactivityStartTimestamp != UNDEFINED_TIMESTAMP) { 1904 return; 1905 } 1906 1907 boolean isInactive = mLastDatagramTransferState.isIdle() && !mIsDeviceAlignedWithSatellite; 1908 if (isInactive) { 1909 mInactivityStartTimestamp = SystemClock.elapsedRealtime(); 1910 } 1911 } 1912 1913 /** 1914 * Updates the max inactivity duration session metric. 1915 * 1916 * <p>This method is called when 1) the datagram transfer state changes to not idle, 2) the 1917 * device is aligned with the satellite, or 3) modem state moves to PowerOffState. 1918 */ endUserInactivity()1919 private void endUserInactivity() { 1920 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 1921 plogd("endUserInactivity: carrierRoamingNbIotNtn is disabled"); 1922 return; 1923 } 1924 1925 if (mInactivityStartTimestamp != UNDEFINED_TIMESTAMP) { 1926 long inactivityDurationMs = SystemClock.elapsedRealtime() - mInactivityStartTimestamp; 1927 int inactivityDurationSec = (int) (inactivityDurationMs / 1000); 1928 mSessionMetricsStats.updateMaxInactivityDurationSec(inactivityDurationSec); 1929 1930 mInactivityStartTimestamp = UNDEFINED_TIMESTAMP; 1931 } 1932 } 1933 handleEventScreenOffInactivityTimerTimedOut()1934 private void handleEventScreenOffInactivityTimerTimedOut() { 1935 if (mSatelliteController.getRequestIsEmergency()) { 1936 loge("handleEventScreenOffInactivityTimerTimedOut: Emergency mode"); 1937 /* This is for coexistence 1938 * mIsEmergency can be set after 1939 * EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT timer started 1940 */ 1941 return; 1942 } 1943 1944 plogd("handleEventScreenOffInactivityTimerTimedOut: request disable satellite"); 1945 1946 mSatelliteController.requestSatelliteEnabled( 1947 false /*enableSatellite*/, 1948 false /*enableDemoMode*/, 1949 mSatelliteController.getRequestIsEmergency() /*isEmergency*/, 1950 new IIntegerConsumer.Stub() { 1951 @Override 1952 public void accept(int result) { 1953 plogd("requestSatelliteEnabled result=" + result); 1954 if (result == SATELLITE_RESULT_SUCCESS) { 1955 mSessionMetricsStats.addCountOfAutoExitDueToScreenOff(); 1956 } 1957 } 1958 }); 1959 } 1960 isMockModemAllowed()1961 private boolean isMockModemAllowed() { 1962 return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false)); 1963 } 1964 getSatelliteStayAtListeningFromSendingMillis()1965 private long getSatelliteStayAtListeningFromSendingMillis() { 1966 if (isDemoMode()) { 1967 return DEMO_MODE_SATELLITE_STAY_AT_LISTENING_MILLIS; 1968 } else { 1969 return mContext.getResources().getInteger( 1970 R.integer.config_satellite_stay_at_listening_from_sending_millis); 1971 } 1972 } 1973 getSatelliteStayAtListeningFromReceivingMillis()1974 private long getSatelliteStayAtListeningFromReceivingMillis() { 1975 if (isDemoMode()) { 1976 return DEMO_MODE_SATELLITE_STAY_AT_LISTENING_MILLIS; 1977 } else { 1978 return mContext.getResources().getInteger( 1979 R.integer.config_satellite_stay_at_listening_from_receiving_millis); 1980 } 1981 } 1982 getSatelliteNbIotInactivityTimeoutMillis()1983 private long getSatelliteNbIotInactivityTimeoutMillis() { 1984 if (isDemoMode()) { 1985 return mContext.getResources().getInteger( 1986 R.integer.config_satellite_demo_mode_nb_iot_inactivity_timeout_millis); 1987 } else { 1988 return mContext.getResources().getInteger( 1989 R.integer.config_satellite_nb_iot_inactivity_timeout_millis); 1990 } 1991 } 1992 restartNbIotInactivityTimer()1993 private void restartNbIotInactivityTimer() { 1994 stopNbIotInactivityTimer(); 1995 startNbIotInactivityTimer(); 1996 } 1997 startNbIotInactivityTimer()1998 private void startNbIotInactivityTimer() { 1999 if (!isSatelliteEnabledForNtnOnlySubscription()) { 2000 plogd("startNbIotInactivityTimer: Can't start timer " 2001 + "because satellite was not enabled for OEM based NB IOT"); 2002 return; 2003 } 2004 2005 if (isNbIotInactivityTimerStarted()) { 2006 plogd("NB IOT inactivity timer is already started"); 2007 return; 2008 } 2009 2010 DatagramController datagramController = DatagramController.getInstance(); 2011 if (datagramController.isSendingInIdleState() 2012 && datagramController.isPollingInIdleState()) { 2013 sendMessageDelayed( 2014 EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT, 2015 mSatelliteNbIotInactivityTimeoutMillis); 2016 } 2017 } 2018 stopNbIotInactivityTimer()2019 private void stopNbIotInactivityTimer() { 2020 removeMessages(EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT); 2021 } 2022 isNbIotInactivityTimerStarted()2023 private boolean isNbIotInactivityTimerStarted() { 2024 return hasMessages(EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT); 2025 } 2026 2027 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) isSatelliteEnabledForNtnOnlySubscription()2028 protected boolean isSatelliteEnabledForNtnOnlySubscription() { 2029 if (SatelliteServiceUtils.getNtnOnlySubscriptionId(mContext) 2030 != getSubId()) { 2031 plogd("isSatelliteEnabledForOemBasedNbIot: highest priority satellite subscription " 2032 + "is not NTN-only subscription"); 2033 return false; 2034 } 2035 2036 return true; 2037 } 2038 isP2pSmsSupportedOnCarrierRoamingNtn(int subId)2039 private boolean isP2pSmsSupportedOnCarrierRoamingNtn(int subId) { 2040 if (!mSatelliteController.isSatelliteRoamingP2pSmSSupported(subId)) { 2041 if (DBG) plogd("isP2pSmsSupportedOnCarrierRoamingNtn: P2P_SMS is not supported"); 2042 return false; 2043 } 2044 2045 int[] services = mSatelliteController.getSupportedServicesOnCarrierRoamingNtn(subId); 2046 if (!ArrayUtils.contains(services, NetworkRegistrationInfo.SERVICE_TYPE_SMS)) { 2047 if (DBG) { 2048 plogd("isP2pSmsSupportedOnCarrierRoamingNtn: P2P_SMS service is not supported " 2049 + "on carrier roaming ntn."); 2050 } 2051 return false; 2052 } 2053 2054 if (DBG) plogd("isP2pSmsSupportedOnCarrierRoamingNtn: P2_SMS is supported"); 2055 return true; 2056 } 2057 isConcurrentTnScanningSupported()2058 private boolean isConcurrentTnScanningSupported() { 2059 if (mIsConcurrentTnScanningSupportedForCtsTest != null) { 2060 plogd("isConcurrentTnScanningSupported: mIsConcurrentTnScanningSupportedForCtsTest=" 2061 + mIsConcurrentTnScanningSupportedForCtsTest); 2062 return mIsConcurrentTnScanningSupportedForCtsTest; 2063 } 2064 try { 2065 return mContext.getResources().getBoolean( 2066 R.bool.config_satellite_modem_support_concurrent_tn_scanning); 2067 } catch (RuntimeException e) { 2068 plogd("isConcurrentTnScanningSupported: ex=" + e); 2069 return false; 2070 } 2071 } 2072 isTnScanningAllowedDuringSatelliteSession()2073 private boolean isTnScanningAllowedDuringSatelliteSession() { 2074 if (mIsTnScanningDuringSatelliteSessionAllowedForCtsTest != null) { 2075 plogd("isTnScanningAllowedDuringSatelliteSession: " 2076 + "mIsTnScanningDuringSatelliteSessionAllowedForCtsTest=" 2077 + mIsTnScanningDuringSatelliteSessionAllowedForCtsTest); 2078 return mIsTnScanningDuringSatelliteSessionAllowedForCtsTest; 2079 } 2080 try { 2081 return mContext.getResources().getBoolean( 2082 R.bool.config_satellite_allow_tn_scanning_during_satellite_session); 2083 } catch (RuntimeException e) { 2084 plogd("isTnScanningAllowedDuringSatelliteSession: ex=" + e); 2085 return false; 2086 } 2087 } 2088 plogd(@onNull String log)2089 private void plogd(@NonNull String log) { 2090 logd(log); 2091 if (mPersistentLogger != null) { 2092 mPersistentLogger.debug(TAG, log); 2093 } 2094 } 2095 plogw(@onNull String log)2096 private void plogw(@NonNull String log) { 2097 logw(log); 2098 if (mPersistentLogger != null) { 2099 mPersistentLogger.warn(TAG, log); 2100 } 2101 } 2102 ploge(@onNull String log)2103 private void ploge(@NonNull String log) { 2104 loge(log); 2105 if (mPersistentLogger != null) { 2106 mPersistentLogger.error(TAG, log); 2107 } 2108 } 2109 } 2110