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.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE; 20 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED; 21 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE; 22 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS; 23 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING; 24 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING; 25 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED; 26 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS; 27 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT; 28 29 import android.annotation.NonNull; 30 import android.annotation.Nullable; 31 import android.content.ComponentName; 32 import android.content.Context; 33 import android.content.Intent; 34 import android.content.ServiceConnection; 35 import android.os.AsyncResult; 36 import android.os.Build; 37 import android.os.IBinder; 38 import android.os.Looper; 39 import android.os.Message; 40 import android.os.RemoteException; 41 import android.os.SystemProperties; 42 import android.telephony.DropBoxManagerLoggerBackend; 43 import android.telephony.PersistentLogger; 44 import android.telephony.Rlog; 45 import android.telephony.satellite.ISatelliteModemStateCallback; 46 import android.telephony.satellite.SatelliteManager; 47 import android.telephony.satellite.stub.ISatelliteGateway; 48 import android.telephony.satellite.stub.SatelliteGatewayService; 49 import android.text.TextUtils; 50 import android.util.Log; 51 52 import com.android.internal.R; 53 import com.android.internal.annotations.GuardedBy; 54 import com.android.internal.annotations.VisibleForTesting; 55 import com.android.internal.telephony.ExponentialBackoff; 56 import com.android.internal.telephony.flags.FeatureFlags; 57 import com.android.internal.util.State; 58 import com.android.internal.util.StateMachine; 59 60 import java.util.ArrayList; 61 import java.util.List; 62 import java.util.concurrent.ConcurrentHashMap; 63 import java.util.concurrent.atomic.AtomicBoolean; 64 65 /** 66 * This module is responsible for managing session state transition and inform listeners of modem 67 * state changed events accordingly. 68 */ 69 public class SatelliteSessionController extends StateMachine { 70 private static final String TAG = "SatelliteSessionController"; 71 private static final boolean DBG = true; 72 private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem"; 73 private static final boolean DEBUG = !"user".equals(Build.TYPE); 74 75 /** 76 * The time duration in millis that the satellite will stay at listening mode to wait for the 77 * next incoming page before disabling listening mode when transitioning from sending mode. 78 */ 79 public static final String SATELLITE_STAY_AT_LISTENING_FROM_SENDING_MILLIS = 80 "satellite_stay_at_listening_from_sending_millis"; 81 /** 82 * The default value of {@link #SATELLITE_STAY_AT_LISTENING_FROM_SENDING_MILLIS}. 83 */ 84 public static final long DEFAULT_SATELLITE_STAY_AT_LISTENING_FROM_SENDING_MILLIS = 180000; 85 /** 86 * The time duration in millis that the satellite will stay at listening mode to wait for the 87 * next incoming page before disabling listening mode when transitioning from receiving mode. 88 */ 89 public static final String SATELLITE_STAY_AT_LISTENING_FROM_RECEIVING_MILLIS = 90 "satellite_stay_at_listening_from_receiving_millis"; 91 /** 92 * The default value of {@link #SATELLITE_STAY_AT_LISTENING_FROM_RECEIVING_MILLIS} 93 */ 94 public static final long DEFAULT_SATELLITE_STAY_AT_LISTENING_FROM_RECEIVING_MILLIS = 30000; 95 /** 96 * The default value of {@link #SATELLITE_STAY_AT_LISTENING_FROM_SENDING_MILLIS}, 97 * and {@link #SATELLITE_STAY_AT_LISTENING_FROM_RECEIVING_MILLIS} for demo mode 98 */ 99 public static final long DEMO_MODE_SATELLITE_STAY_AT_LISTENING_MILLIS = 3000; 100 101 private static final int EVENT_DATAGRAM_TRANSFER_STATE_CHANGED = 1; 102 private static final int EVENT_LISTENING_TIMER_TIMEOUT = 2; 103 private static final int EVENT_SATELLITE_ENABLED_STATE_CHANGED = 3; 104 private static final int EVENT_SATELLITE_MODEM_STATE_CHANGED = 4; 105 private static final int EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE = 5; 106 protected static final int EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT = 6; 107 private static final int EVENT_SATELLITE_ENABLEMENT_STARTED = 7; 108 private static final int EVENT_SATELLITE_ENABLEMENT_FAILED = 8; 109 110 private static final long REBIND_INITIAL_DELAY = 2 * 1000; // 2 seconds 111 private static final long REBIND_MAXIMUM_DELAY = 64 * 1000; // 1 minute 112 private static final int REBIND_MULTIPLIER = 2; 113 @NonNull private final ExponentialBackoff mExponentialBackoff; 114 @NonNull private final Object mLock = new Object(); 115 @Nullable 116 private ISatelliteGateway mSatelliteGatewayService; 117 private String mSatelliteGatewayServicePackageName = ""; 118 @Nullable private SatelliteGatewayServiceConnection mSatelliteGatewayServiceConnection; 119 private boolean mIsBound; 120 private boolean mIsBinding; 121 122 @NonNull private static SatelliteSessionController sInstance; 123 124 @NonNull private final Context mContext; 125 @NonNull private final SatelliteModemInterface mSatelliteModemInterface; 126 @NonNull private final UnavailableState mUnavailableState = new UnavailableState(); 127 @NonNull private final PowerOffState mPowerOffState = new PowerOffState(); 128 @NonNull private final EnablingState mEnablingState = new EnablingState(); 129 @NonNull private final DisablingState mDisablingState = new DisablingState(); 130 @NonNull private final IdleState mIdleState = new IdleState(); 131 @NonNull private final TransferringState mTransferringState = new TransferringState(); 132 @NonNull private final ListeningState mListeningState = new ListeningState(); 133 @NonNull private final NotConnectedState mNotConnectedState = new NotConnectedState(); 134 @NonNull private final ConnectedState mConnectedState = new ConnectedState(); 135 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 136 protected AtomicBoolean mIsSendingTriggeredDuringTransferringState; 137 private long mSatelliteStayAtListeningFromSendingMillis; 138 private long mSatelliteStayAtListeningFromReceivingMillis; 139 private long mSatelliteNbIotInactivityTimeoutMillis; 140 private final ConcurrentHashMap<IBinder, ISatelliteModemStateCallback> mListeners; 141 @SatelliteManager.SatelliteModemState private int mCurrentState; 142 final boolean mIsSatelliteSupported; 143 private boolean mIsDemoMode = false; 144 @GuardedBy("mLock") 145 @NonNull private boolean mIsDisableCellularModemInProgress = false; 146 @NonNull private final SatelliteController mSatelliteController; 147 @NonNull private final DatagramController mDatagramController; 148 @Nullable private PersistentLogger mPersistentLogger = null; 149 150 151 /** 152 * @return The singleton instance of SatelliteSessionController. 153 */ getInstance()154 public static SatelliteSessionController getInstance() { 155 if (sInstance == null) { 156 Log.e(TAG, "SatelliteSessionController was not yet initialized."); 157 } 158 return sInstance; 159 } 160 161 /** 162 * Create the SatelliteSessionController singleton instance. 163 * 164 * @param context The Context for the SatelliteSessionController. 165 * @param looper The looper associated with the handler of this class. 166 * @param featureFlags The telephony feature flags. 167 * @param isSatelliteSupported Whether satellite is supported on the device. 168 * @return The singleton instance of SatelliteSessionController. 169 */ make( @onNull Context context, @NonNull Looper looper, @NonNull FeatureFlags featureFlags, boolean isSatelliteSupported)170 public static SatelliteSessionController make( 171 @NonNull Context context, 172 @NonNull Looper looper, 173 @NonNull FeatureFlags featureFlags, 174 boolean isSatelliteSupported) { 175 if (sInstance == null || isSatelliteSupported != sInstance.mIsSatelliteSupported) { 176 sInstance = new SatelliteSessionController( 177 context, 178 looper, 179 featureFlags, 180 isSatelliteSupported, 181 SatelliteModemInterface.getInstance()); 182 } 183 return sInstance; 184 } 185 186 /** 187 * Create a SatelliteSessionController to manage satellite session. 188 * 189 * @param context The Context for the SatelliteSessionController. 190 * @param looper The looper associated with the handler of this class. 191 * @param featureFlags The telephony feature flags. 192 * @param isSatelliteSupported Whether satellite is supported on the device. 193 * @param satelliteModemInterface The singleton of SatelliteModemInterface. 194 */ 195 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) SatelliteSessionController(@onNull Context context, @NonNull Looper looper, @NonNull FeatureFlags featureFlags, boolean isSatelliteSupported, @NonNull SatelliteModemInterface satelliteModemInterface)196 protected SatelliteSessionController(@NonNull Context context, @NonNull Looper looper, 197 @NonNull FeatureFlags featureFlags, 198 boolean isSatelliteSupported, 199 @NonNull SatelliteModemInterface satelliteModemInterface) { 200 super(TAG, looper); 201 202 if (isSatellitePersistentLoggingEnabled(context, featureFlags)) { 203 mPersistentLogger = new PersistentLogger( 204 DropBoxManagerLoggerBackend.getInstance(context)); 205 } 206 207 mContext = context; 208 mSatelliteModemInterface = satelliteModemInterface; 209 mSatelliteController = SatelliteController.getInstance(); 210 mDatagramController = DatagramController.getInstance(); 211 mSatelliteStayAtListeningFromSendingMillis = getSatelliteStayAtListeningFromSendingMillis(); 212 mSatelliteStayAtListeningFromReceivingMillis = 213 getSatelliteStayAtListeningFromReceivingMillis(); 214 mSatelliteNbIotInactivityTimeoutMillis = 215 getSatelliteNbIotInactivityTimeoutMillis(); 216 mListeners = new ConcurrentHashMap<>(); 217 mIsSendingTriggeredDuringTransferringState = new AtomicBoolean(false); 218 mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN; 219 mIsSatelliteSupported = isSatelliteSupported; 220 mExponentialBackoff = new ExponentialBackoff(REBIND_INITIAL_DELAY, REBIND_MAXIMUM_DELAY, 221 REBIND_MULTIPLIER, looper, () -> { 222 synchronized (mLock) { 223 if ((mIsBound && mSatelliteGatewayService != null) || mIsBinding) { 224 return; 225 } 226 } 227 if (mSatelliteGatewayServiceConnection != null) { 228 synchronized (mLock) { 229 mIsBound = false; 230 mIsBinding = false; 231 } 232 unbindService(); 233 } 234 bindService(); 235 }); 236 237 addState(mUnavailableState); 238 addState(mPowerOffState); 239 addState(mEnablingState); 240 addState(mDisablingState); 241 addState(mIdleState); 242 addState(mTransferringState); 243 addState(mListeningState); 244 addState(mNotConnectedState); 245 addState(mConnectedState); 246 setInitialState(isSatelliteSupported); 247 start(); 248 } 249 250 /** 251 * {@link DatagramController} uses this function to notify {@link SatelliteSessionController} 252 * that its datagram transfer state has changed. 253 * 254 * @param sendState The current datagram send state of {@link DatagramController}. 255 * @param receiveState The current datagram receive state of {@link DatagramController}. 256 */ 257 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) onDatagramTransferStateChanged( @atelliteManager.SatelliteDatagramTransferState int sendState, @SatelliteManager.SatelliteDatagramTransferState int receiveState)258 public void onDatagramTransferStateChanged( 259 @SatelliteManager.SatelliteDatagramTransferState int sendState, 260 @SatelliteManager.SatelliteDatagramTransferState int receiveState) { 261 sendMessage(EVENT_DATAGRAM_TRANSFER_STATE_CHANGED, 262 new DatagramTransferState(sendState, receiveState)); 263 if (sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING) { 264 mIsSendingTriggeredDuringTransferringState.set(true); 265 } 266 } 267 268 /** 269 * {@link SatelliteController} uses this function to notify {@link SatelliteSessionController} 270 * that the satellite enabled state has changed. 271 * 272 * @param enabled {@code true} means enabled and {@code false} means disabled. 273 */ 274 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) onSatelliteEnabledStateChanged(boolean enabled)275 public void onSatelliteEnabledStateChanged(boolean enabled) { 276 sendMessage(EVENT_SATELLITE_ENABLED_STATE_CHANGED, enabled); 277 } 278 279 /** 280 * {@link SatelliteController} uses this function to notify {@link SatelliteSessionController} 281 * that the satellite enablement has just started. 282 * 283 * @param enabled {@code true} means being enabled and {@code false} means being disabled. 284 */ 285 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) onSatelliteEnablementStarted(boolean enabled)286 public void onSatelliteEnablementStarted(boolean enabled) { 287 sendMessage(EVENT_SATELLITE_ENABLEMENT_STARTED, enabled); 288 } 289 290 /** 291 * {@link SatelliteController} uses this function to notify {@link SatelliteSessionController} 292 * that the satellite enablement has just failed. 293 */ 294 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) onSatelliteEnablementFailed()295 public void onSatelliteEnablementFailed() { 296 sendMessage(EVENT_SATELLITE_ENABLEMENT_FAILED); 297 } 298 299 /** 300 * {@link SatelliteController} uses this function to notify {@link SatelliteSessionController} 301 * that the satellite modem state has changed. 302 * 303 * @param state The current state of the satellite modem. 304 */ 305 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) onSatelliteModemStateChanged(@atelliteManager.SatelliteModemState int state)306 public void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state) { 307 sendMessage(EVENT_SATELLITE_MODEM_STATE_CHANGED, state); 308 } 309 310 /** 311 * Registers for modem state changed from satellite modem. 312 * 313 * @param callback The callback to handle the satellite modem state changed event. 314 */ registerForSatelliteModemStateChanged( @onNull ISatelliteModemStateCallback callback)315 public void registerForSatelliteModemStateChanged( 316 @NonNull ISatelliteModemStateCallback callback) { 317 try { 318 callback.onSatelliteModemStateChanged(mCurrentState); 319 mListeners.put(callback.asBinder(), callback); 320 } catch (RemoteException ex) { 321 ploge("registerForSatelliteModemStateChanged: Got RemoteException ex=" + ex); 322 } 323 } 324 325 /** 326 * Unregisters for modem state changed from satellite modem. 327 * If callback was not registered before, the request will be ignored. 328 * 329 * @param callback The callback that was passed to 330 * {@link #registerForSatelliteModemStateChanged(ISatelliteModemStateCallback)}. 331 */ unregisterForSatelliteModemStateChanged( @onNull ISatelliteModemStateCallback callback)332 public void unregisterForSatelliteModemStateChanged( 333 @NonNull ISatelliteModemStateCallback callback) { 334 mListeners.remove(callback.asBinder()); 335 } 336 337 /** 338 * This API can be used by only CTS to update the timeout duration in milliseconds that 339 * satellite should stay at listening mode to wait for the next incoming page before disabling 340 * listening mode. 341 * 342 * @param timeoutMillis The timeout duration in millisecond. 343 * @return {@code true} if the timeout duration is set successfully, {@code false} otherwise. 344 */ setSatelliteListeningTimeoutDuration(long timeoutMillis)345 boolean setSatelliteListeningTimeoutDuration(long timeoutMillis) { 346 if (!isMockModemAllowed()) { 347 ploge("Updating listening timeout duration is not allowed"); 348 return false; 349 } 350 351 plogd("setSatelliteListeningTimeoutDuration: timeoutMillis=" + timeoutMillis); 352 if (timeoutMillis == 0) { 353 mSatelliteStayAtListeningFromSendingMillis = 354 getSatelliteStayAtListeningFromSendingMillis(); 355 mSatelliteStayAtListeningFromReceivingMillis = 356 getSatelliteStayAtListeningFromReceivingMillis(); 357 mSatelliteNbIotInactivityTimeoutMillis = 358 getSatelliteNbIotInactivityTimeoutMillis(); 359 } else { 360 mSatelliteStayAtListeningFromSendingMillis = timeoutMillis; 361 mSatelliteStayAtListeningFromReceivingMillis = timeoutMillis; 362 mSatelliteNbIotInactivityTimeoutMillis = timeoutMillis; 363 } 364 365 return true; 366 } 367 368 /** 369 * This API can be used by only CTS to update satellite gateway service package name. 370 * 371 * @param servicePackageName The package name of the satellite gateway service. 372 * @return {@code true} if the satellite gateway service is set successfully, 373 * {@code false} otherwise. 374 */ setSatelliteGatewayServicePackageName(@ullable String servicePackageName)375 boolean setSatelliteGatewayServicePackageName(@Nullable String servicePackageName) { 376 if (!isMockModemAllowed()) { 377 ploge("setSatelliteGatewayServicePackageName: modifying satellite gateway service " 378 + "package name is not allowed"); 379 return false; 380 } 381 382 plogd("setSatelliteGatewayServicePackageName: config_satellite_gateway_service_package is " 383 + "updated, new packageName=" + servicePackageName); 384 385 if (servicePackageName == null || servicePackageName.equals("null")) { 386 mSatelliteGatewayServicePackageName = ""; 387 } else { 388 mSatelliteGatewayServicePackageName = servicePackageName; 389 } 390 391 if (mSatelliteGatewayServiceConnection != null) { 392 synchronized (mLock) { 393 mIsBound = false; 394 mIsBinding = false; 395 } 396 unbindService(); 397 bindService(); 398 } 399 return true; 400 } 401 402 /** 403 * Adjusts listening timeout duration when demo mode is on 404 * 405 * @param isDemoMode {@code true} : The listening timeout durations will be set to 406 * {@link #DEMO_MODE_SATELLITE_STAY_AT_LISTENING_MILLIS} 407 * {@code false} : The listening timeout durations will be restored to 408 * production mode 409 */ 410 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) setDemoMode(boolean isDemoMode)411 public void setDemoMode(boolean isDemoMode) { 412 mIsDemoMode = isDemoMode; 413 } 414 415 /** 416 * Get whether state machine is in enabling state. 417 * 418 * @return {@code true} if state machine is in enabling state and {@code false} otherwise. 419 */ isInEnablingState()420 public boolean isInEnablingState() { 421 if (DBG) plogd("isInEnablingState: getCurrentState=" + getCurrentState()); 422 return getCurrentState() == mEnablingState; 423 } 424 isDemoMode()425 private boolean isDemoMode() { 426 return mIsDemoMode; 427 } 428 429 private static class DatagramTransferState { 430 @SatelliteManager.SatelliteDatagramTransferState public int sendState; 431 @SatelliteManager.SatelliteDatagramTransferState public int receiveState; 432 DatagramTransferState(@atelliteManager.SatelliteDatagramTransferState int sendState, @SatelliteManager.SatelliteDatagramTransferState int receiveState)433 DatagramTransferState(@SatelliteManager.SatelliteDatagramTransferState int sendState, 434 @SatelliteManager.SatelliteDatagramTransferState int receiveState) { 435 this.sendState = sendState; 436 this.receiveState = receiveState; 437 } 438 } 439 440 private class UnavailableState extends State { 441 @Override enter()442 public void enter() { 443 if (DBG) plogd("Entering UnavailableState"); 444 mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE; 445 notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE); 446 } 447 448 @Override processMessage(Message msg)449 public boolean processMessage(Message msg) { 450 ploge("UnavailableState: receive msg " + getWhatToString(msg.what) + " unexpectedly"); 451 return HANDLED; 452 } 453 } 454 455 private class PowerOffState extends State { 456 @Override enter()457 public void enter() { 458 if (DBG) plogd("Entering PowerOffState"); 459 460 mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_OFF; 461 mIsSendingTriggeredDuringTransferringState.set(false); 462 synchronized (mLock) { 463 mIsDisableCellularModemInProgress = false; 464 } 465 unbindService(); 466 stopNbIotInactivityTimer(); 467 DemoSimulator.getInstance().onSatelliteModeOff(); 468 notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_OFF); 469 } 470 471 @Override exit()472 public void exit() { 473 if (DBG) plogd("Exiting PowerOffState"); 474 plogd("Attempting to bind to SatelliteGatewayService."); 475 bindService(); 476 } 477 478 @Override processMessage(Message msg)479 public boolean processMessage(Message msg) { 480 if (DBG) plogd("PowerOffState: processing " + getWhatToString(msg.what)); 481 switch (msg.what) { 482 case EVENT_SATELLITE_ENABLEMENT_STARTED: 483 handleSatelliteEnablementStarted((boolean) msg.obj); 484 break; 485 } 486 // Ignore all unexpected events. 487 return HANDLED; 488 } 489 handleSatelliteEnablementStarted(boolean enabled)490 private void handleSatelliteEnablementStarted(boolean enabled) { 491 if (enabled) { 492 transitionTo(mEnablingState); 493 } else { 494 plogw("Unexpected satellite disablement started in PowerOff state"); 495 } 496 } 497 } 498 499 private class EnablingState extends State { 500 @Override enter()501 public void enter() { 502 if (DBG) plogd("Entering EnablingState"); 503 504 mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_ENABLING_SATELLITE; 505 notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_ENABLING_SATELLITE); 506 } 507 508 @Override exit()509 public void exit() { 510 if (DBG) plogd("Exiting EnablingState"); 511 } 512 513 @Override processMessage(Message msg)514 public boolean processMessage(Message msg) { 515 if (DBG) plogd("EnablingState: processing " + getWhatToString(msg.what)); 516 switch (msg.what) { 517 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 518 handleSatelliteEnabledStateChanged((boolean) msg.obj); 519 break; 520 case EVENT_SATELLITE_ENABLEMENT_FAILED: 521 transitionTo(mPowerOffState); 522 break; 523 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 524 deferMessage(msg); 525 break; 526 } 527 // Ignore all unexpected events. 528 return HANDLED; 529 } 530 handleSatelliteEnabledStateChanged(boolean on)531 private void handleSatelliteEnabledStateChanged(boolean on) { 532 if (on) { 533 if (mSatelliteController.isSatelliteAttachRequired()) { 534 transitionTo(mNotConnectedState); 535 } else { 536 transitionTo(mIdleState); 537 } 538 DemoSimulator.getInstance().onSatelliteModeOn(); 539 } else { 540 /* 541 * During the state transition from ENABLING to NOT_CONNECTED, modem might be 542 * reset. In such cases, we need to remove all deferred 543 * EVENT_SATELLITE_MODEM_STATE_CHANGED events so that they will not mess up our 544 * state machine later. 545 */ 546 removeDeferredMessages(EVENT_SATELLITE_MODEM_STATE_CHANGED); 547 transitionTo(mPowerOffState); 548 } 549 } 550 } 551 552 private class DisablingState extends State { 553 @Override enter()554 public void enter() { 555 if (DBG) plogd("Entering DisablingState"); 556 557 mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_DISABLING_SATELLITE; 558 notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_DISABLING_SATELLITE); 559 } 560 561 @Override exit()562 public void exit() { 563 if (DBG) plogd("Exiting DisablingState"); 564 } 565 566 @Override processMessage(Message msg)567 public boolean processMessage(Message msg) { 568 if (DBG) plogd("DisablingState: processing " + getWhatToString(msg.what)); 569 switch (msg.what) { 570 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 571 handleSatelliteEnabledStateChanged((boolean) msg.obj); 572 break; 573 } 574 // Ignore all unexpected events. 575 return HANDLED; 576 } 577 handleSatelliteEnabledStateChanged(boolean on)578 private void handleSatelliteEnabledStateChanged(boolean on) { 579 if (on) { 580 plogw("Unexpected power on event while disabling satellite"); 581 } else { 582 transitionTo(mPowerOffState); 583 } 584 } 585 } 586 587 private class IdleState extends State { 588 @Override enter()589 public void enter() { 590 if (DBG) plogd("Entering IdleState"); 591 mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_IDLE; 592 mIsSendingTriggeredDuringTransferringState.set(false); 593 stopNbIotInactivityTimer(); 594 //Enable Cellular Modem scanning 595 mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(true, null); 596 notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_IDLE); 597 } 598 599 @Override processMessage(Message msg)600 public boolean processMessage(Message msg) { 601 if (DBG) plogd("IdleState: processing " + getWhatToString(msg.what)); 602 switch (msg.what) { 603 case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED: 604 handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj); 605 break; 606 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 607 handleSatelliteEnabledStateChanged(!(boolean) msg.obj, "IdleState"); 608 break; 609 case EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE: 610 handleEventDisableCellularModemWhileSatelliteModeIsOnDone( 611 (AsyncResult) msg.obj); 612 break; 613 case EVENT_SATELLITE_ENABLEMENT_STARTED: 614 handleSatelliteEnablementStarted((boolean) msg.obj); 615 break; 616 } 617 // Ignore all unexpected events. 618 return HANDLED; 619 } 620 handleEventDatagramTransferStateChanged( @onNull DatagramTransferState datagramTransferState)621 private void handleEventDatagramTransferStateChanged( 622 @NonNull DatagramTransferState datagramTransferState) { 623 if ((datagramTransferState.sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING) 624 || (datagramTransferState.receiveState 625 == SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING)) { 626 if (mSatelliteController.isSatelliteAttachRequired()) { 627 ploge("Unexpected transferring state received for NB-IOT NTN"); 628 } else { 629 transitionTo(mTransferringState); 630 } 631 } else if ((datagramTransferState.sendState 632 == SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT) 633 || (datagramTransferState.receiveState 634 == SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT)) { 635 if (mSatelliteController.isSatelliteAttachRequired()) { 636 disableCellularModemWhileSatelliteModeIsOn(); 637 } else { 638 ploge("Unexpected transferring state received for non-NB-IOT NTN"); 639 } 640 } 641 } 642 handleEventDisableCellularModemWhileSatelliteModeIsOnDone( @onNull AsyncResult result)643 private void handleEventDisableCellularModemWhileSatelliteModeIsOnDone( 644 @NonNull AsyncResult result) { 645 synchronized (mLock) { 646 if (mIsDisableCellularModemInProgress) { 647 int error = SatelliteServiceUtils.getSatelliteError( 648 result, "DisableCellularModemWhileSatelliteModeIsOnDone"); 649 if (error == SatelliteManager.SATELLITE_RESULT_SUCCESS) { 650 transitionTo(mNotConnectedState); 651 } 652 mIsDisableCellularModemInProgress = false; 653 } else { 654 ploge("DisableCellularModemWhileSatelliteModeIsOn is not in progress"); 655 } 656 } 657 } 658 disableCellularModemWhileSatelliteModeIsOn()659 private void disableCellularModemWhileSatelliteModeIsOn() { 660 synchronized (mLock) { 661 if (mIsDisableCellularModemInProgress) { 662 plogd("Cellular scanning is already being disabled"); 663 return; 664 } 665 666 mIsDisableCellularModemInProgress = true; 667 Message onCompleted = 668 obtainMessage(EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE); 669 mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(false, 670 onCompleted); 671 } 672 } 673 674 @Override exit()675 public void exit() { 676 if (DBG) plogd("Exiting IdleState"); 677 if (!mSatelliteController.isSatelliteAttachRequired()) { 678 // Disable cellular modem scanning 679 mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(false, null); 680 } 681 } 682 } 683 684 private class TransferringState extends State { 685 @Override enter()686 public void enter() { 687 if (DBG) plogd("Entering TransferringState"); 688 stopNbIotInactivityTimer(); 689 mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING; 690 notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING); 691 } 692 693 @Override processMessage(Message msg)694 public boolean processMessage(Message msg) { 695 if (DBG) plogd("TransferringState: processing " + getWhatToString(msg.what)); 696 switch (msg.what) { 697 case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED: 698 handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj); 699 return HANDLED; 700 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 701 handleSatelliteEnabledStateChanged(!(boolean) msg.obj, "TransferringState"); 702 break; 703 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 704 handleEventSatelliteModemStateChange(msg.arg1); 705 break; 706 case EVENT_SATELLITE_ENABLEMENT_STARTED: 707 handleSatelliteEnablementStarted((boolean) msg.obj); 708 break; 709 } 710 // Ignore all unexpected events. 711 return HANDLED; 712 } 713 handleEventDatagramTransferStateChanged( @onNull DatagramTransferState datagramTransferState)714 private void handleEventDatagramTransferStateChanged( 715 @NonNull DatagramTransferState datagramTransferState) { 716 if (isSending(datagramTransferState.sendState) || isReceiving( 717 datagramTransferState.receiveState)) { 718 // Stay at transferring state. 719 } else { 720 if (mSatelliteController.isSatelliteAttachRequired()) { 721 transitionTo(mConnectedState); 722 } else { 723 if ((datagramTransferState.sendState 724 == SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED) 725 || (datagramTransferState.receiveState 726 == SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED)) { 727 transitionTo(mIdleState); 728 } else { 729 transitionTo(mListeningState); 730 } 731 } 732 } 733 } 734 handleEventSatelliteModemStateChange( @atelliteManager.SatelliteModemState int state)735 private void handleEventSatelliteModemStateChange( 736 @SatelliteManager.SatelliteModemState int state) { 737 if (state == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED) { 738 transitionTo(mNotConnectedState); 739 } 740 } 741 } 742 743 private class ListeningState extends State { 744 @Override enter()745 public void enter() { 746 if (DBG) plogd("Entering ListeningState"); 747 748 mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_LISTENING; 749 long timeoutMillis = updateListeningMode(true); 750 sendMessageDelayed(EVENT_LISTENING_TIMER_TIMEOUT, timeoutMillis); 751 mIsSendingTriggeredDuringTransferringState.set(false); 752 notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_LISTENING); 753 } 754 755 @Override exit()756 public void exit() { 757 if (DBG) plogd("Exiting ListeningState"); 758 759 removeMessages(EVENT_LISTENING_TIMER_TIMEOUT); 760 updateListeningMode(false); 761 } 762 763 @Override processMessage(Message msg)764 public boolean processMessage(Message msg) { 765 if (DBG) plogd("ListeningState: processing " + getWhatToString(msg.what)); 766 switch (msg.what) { 767 case EVENT_LISTENING_TIMER_TIMEOUT: 768 transitionTo(mIdleState); 769 break; 770 case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED: 771 handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj); 772 break; 773 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 774 handleSatelliteEnabledStateChanged(!(boolean) msg.obj, "ListeningState"); 775 break; 776 case EVENT_SATELLITE_ENABLEMENT_STARTED: 777 handleSatelliteEnablementStarted((boolean) msg.obj); 778 break; 779 } 780 // Ignore all unexpected events. 781 return HANDLED; 782 } 783 updateListeningMode(boolean enabled)784 private long updateListeningMode(boolean enabled) { 785 long timeoutMillis; 786 if (mIsSendingTriggeredDuringTransferringState.get()) { 787 timeoutMillis = mSatelliteStayAtListeningFromSendingMillis; 788 } else { 789 timeoutMillis = mSatelliteStayAtListeningFromReceivingMillis; 790 } 791 mSatelliteModemInterface.requestSatelliteListeningEnabled( 792 enabled, (int) timeoutMillis, null); 793 return timeoutMillis; 794 } 795 handleEventDatagramTransferStateChanged( @onNull DatagramTransferState datagramTransferState)796 private void handleEventDatagramTransferStateChanged( 797 @NonNull DatagramTransferState datagramTransferState) { 798 if (datagramTransferState.sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING 799 || datagramTransferState.receiveState 800 == SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING) { 801 transitionTo(mTransferringState); 802 } 803 } 804 } 805 806 private class NotConnectedState extends State { 807 @Override enter()808 public void enter() { 809 if (DBG) plogd("Entering NotConnectedState"); 810 811 mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED; 812 notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED); 813 startNbIotInactivityTimer(); 814 } 815 816 @Override exit()817 public void exit() { 818 if (DBG) plogd("Exiting NotConnectedState"); 819 } 820 821 @Override processMessage(Message msg)822 public boolean processMessage(Message msg) { 823 if (DBG) plogd("NotConnectedState: processing " + getWhatToString(msg.what)); 824 switch (msg.what) { 825 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 826 handleSatelliteEnabledStateChanged( 827 !(boolean) msg.obj, "NotConnectedState"); 828 break; 829 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 830 handleEventSatelliteModemStateChanged(msg.arg1); 831 break; 832 case EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT: 833 transitionTo(mIdleState); 834 break; 835 case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED: 836 handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj); 837 break; 838 case EVENT_SATELLITE_ENABLEMENT_STARTED: 839 handleSatelliteEnablementStarted((boolean) msg.obj); 840 break; 841 } 842 // Ignore all unexpected events. 843 return HANDLED; 844 } 845 handleEventSatelliteModemStateChanged( @atelliteManager.SatelliteModemState int state)846 private void handleEventSatelliteModemStateChanged( 847 @SatelliteManager.SatelliteModemState int state) { 848 if (state == SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED) { 849 transitionTo(mConnectedState); 850 } 851 } 852 handleEventDatagramTransferStateChanged( @onNull DatagramTransferState datagramTransferState)853 private void handleEventDatagramTransferStateChanged( 854 @NonNull DatagramTransferState datagramTransferState) { 855 if (datagramTransferState.sendState 856 == SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT 857 || datagramTransferState.receiveState 858 == SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT) { 859 stopNbIotInactivityTimer(); 860 } else if (datagramTransferState.sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE 861 && datagramTransferState.receiveState 862 == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE) { 863 startNbIotInactivityTimer(); 864 } else if (isSending(datagramTransferState.sendState) 865 || isReceiving(datagramTransferState.receiveState)) { 866 restartNbIotInactivityTimer(); 867 } 868 } 869 } 870 871 private class ConnectedState extends State { 872 @Override enter()873 public void enter() { 874 if (DBG) plogd("Entering ConnectedState"); 875 876 mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED; 877 notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED); 878 startNbIotInactivityTimer(); 879 } 880 881 @Override exit()882 public void exit() { 883 if (DBG) plogd("Exiting ConnectedState"); 884 } 885 886 @Override processMessage(Message msg)887 public boolean processMessage(Message msg) { 888 if (DBG) plogd("ConnectedState: processing " + getWhatToString(msg.what)); 889 switch (msg.what) { 890 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 891 handleSatelliteEnabledStateChanged( 892 !(boolean) msg.obj, "ConnectedState"); 893 break; 894 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 895 handleEventSatelliteModemStateChanged(msg.arg1); 896 break; 897 case EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT: 898 transitionTo(mIdleState); 899 break; 900 case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED: 901 handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj); 902 break; 903 case EVENT_SATELLITE_ENABLEMENT_STARTED: 904 handleSatelliteEnablementStarted((boolean) msg.obj); 905 break; 906 } 907 // Ignore all unexpected events. 908 return HANDLED; 909 } 910 handleEventSatelliteModemStateChanged( @atelliteManager.SatelliteModemState int state)911 private void handleEventSatelliteModemStateChanged( 912 @SatelliteManager.SatelliteModemState int state) { 913 if (state == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED) { 914 transitionTo(mNotConnectedState); 915 } 916 } 917 handleEventDatagramTransferStateChanged( @onNull DatagramTransferState datagramTransferState)918 private void handleEventDatagramTransferStateChanged( 919 @NonNull DatagramTransferState datagramTransferState) { 920 if (isSending(datagramTransferState.sendState) 921 || isReceiving(datagramTransferState.receiveState)) { 922 transitionTo(mTransferringState); 923 } 924 } 925 } 926 927 /** 928 * @return the string for msg.what 929 */ 930 @Override getWhatToString(int what)931 protected String getWhatToString(int what) { 932 String whatString; 933 switch (what) { 934 case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED: 935 whatString = "EVENT_DATAGRAM_TRANSFER_STATE_CHANGED"; 936 break; 937 case EVENT_LISTENING_TIMER_TIMEOUT: 938 whatString = "EVENT_LISTENING_TIMER_TIMEOUT"; 939 break; 940 case EVENT_SATELLITE_ENABLED_STATE_CHANGED: 941 whatString = "EVENT_SATELLITE_ENABLED_STATE_CHANGED"; 942 break; 943 case EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE: 944 whatString = "EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE"; 945 break; 946 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 947 whatString = "EVENT_SATELLITE_MODEM_STATE_CHANGED"; 948 break; 949 case EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT: 950 whatString = "EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT"; 951 break; 952 case EVENT_SATELLITE_ENABLEMENT_STARTED: 953 whatString = "EVENT_SATELLITE_ENABLEMENT_STARTED"; 954 break; 955 case EVENT_SATELLITE_ENABLEMENT_FAILED: 956 whatString = "EVENT_SATELLITE_ENABLEMENT_FAILED"; 957 break; 958 default: 959 whatString = "UNKNOWN EVENT " + what; 960 } 961 return whatString; 962 } 963 setInitialState(boolean isSatelliteSupported)964 private void setInitialState(boolean isSatelliteSupported) { 965 if (isSatelliteSupported) { 966 setInitialState(mPowerOffState); 967 } else { 968 setInitialState(mUnavailableState); 969 } 970 } 971 notifyStateChangedEvent(@atelliteManager.SatelliteModemState int state)972 private void notifyStateChangedEvent(@SatelliteManager.SatelliteModemState int state) { 973 mDatagramController.onSatelliteModemStateChanged(state); 974 975 List<ISatelliteModemStateCallback> toBeRemoved = new ArrayList<>(); 976 mListeners.values().forEach(listener -> { 977 try { 978 listener.onSatelliteModemStateChanged(state); 979 } catch (RemoteException e) { 980 plogd("notifyStateChangedEvent RemoteException: " + e); 981 toBeRemoved.add(listener); 982 } 983 }); 984 985 toBeRemoved.forEach(listener -> { 986 mListeners.remove(listener.asBinder()); 987 }); 988 } 989 handleSatelliteEnabledStateChanged(boolean off, String caller)990 private void handleSatelliteEnabledStateChanged(boolean off, String caller) { 991 if (off) { 992 transitionTo(mPowerOffState); 993 } else { 994 ploge(caller + ": Unexpected satellite radio powered-on state changed event"); 995 } 996 } 997 isSending(@atelliteManager.SatelliteDatagramTransferState int sendState)998 private boolean isSending(@SatelliteManager.SatelliteDatagramTransferState int sendState) { 999 return (sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING 1000 || sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS); 1001 } 1002 isReceiving(@atelliteManager.SatelliteDatagramTransferState int receiveState)1003 private boolean isReceiving(@SatelliteManager.SatelliteDatagramTransferState int receiveState) { 1004 return (receiveState == SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING 1005 || receiveState == SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS 1006 || receiveState == SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE); 1007 } 1008 1009 @NonNull getSatelliteGatewayPackageName()1010 private String getSatelliteGatewayPackageName() { 1011 if (!TextUtils.isEmpty(mSatelliteGatewayServicePackageName)) { 1012 return mSatelliteGatewayServicePackageName; 1013 } 1014 return TextUtils.emptyIfNull(mContext.getResources().getString( 1015 R.string.config_satellite_gateway_service_package)); 1016 } 1017 bindService()1018 private void bindService() { 1019 synchronized (mLock) { 1020 if (mIsBinding || mIsBound) return; 1021 mIsBinding = true; 1022 } 1023 mExponentialBackoff.start(); 1024 1025 String packageName = getSatelliteGatewayPackageName(); 1026 if (TextUtils.isEmpty(packageName)) { 1027 ploge("Unable to bind to the satellite gateway service because the package is" 1028 + " undefined."); 1029 // Since the package name comes from static device configs, stop retry because 1030 // rebind will continue to fail without a valid package name. 1031 synchronized (mLock) { 1032 mIsBinding = false; 1033 } 1034 mExponentialBackoff.stop(); 1035 return; 1036 } 1037 Intent intent = new Intent(SatelliteGatewayService.SERVICE_INTERFACE); 1038 intent.setPackage(packageName); 1039 1040 mSatelliteGatewayServiceConnection = new SatelliteGatewayServiceConnection(); 1041 try { 1042 boolean success = mContext.bindService( 1043 intent, mSatelliteGatewayServiceConnection, Context.BIND_AUTO_CREATE); 1044 if (success) { 1045 plogd("Successfully bound to the satellite gateway service."); 1046 } else { 1047 synchronized (mLock) { 1048 mIsBinding = false; 1049 } 1050 mExponentialBackoff.notifyFailed(); 1051 ploge("Error binding to the satellite gateway service. Retrying in " 1052 + mExponentialBackoff.getCurrentDelay() + " ms."); 1053 } 1054 } catch (Exception e) { 1055 synchronized (mLock) { 1056 mIsBinding = false; 1057 } 1058 mExponentialBackoff.notifyFailed(); 1059 ploge("Exception binding to the satellite gateway service. Retrying in " 1060 + mExponentialBackoff.getCurrentDelay() + " ms. Exception: " + e); 1061 } 1062 } 1063 unbindService()1064 private void unbindService() { 1065 plogd("unbindService"); 1066 mExponentialBackoff.stop(); 1067 mSatelliteGatewayService = null; 1068 synchronized (mLock) { 1069 mIsBinding = false; 1070 mIsBound = false; 1071 } 1072 if (mSatelliteGatewayServiceConnection != null) { 1073 mContext.unbindService(mSatelliteGatewayServiceConnection); 1074 mSatelliteGatewayServiceConnection = null; 1075 } 1076 } 1077 private class SatelliteGatewayServiceConnection implements ServiceConnection { 1078 @Override onServiceConnected(ComponentName name, IBinder service)1079 public void onServiceConnected(ComponentName name, IBinder service) { 1080 plogd("onServiceConnected: ComponentName=" + name); 1081 synchronized (mLock) { 1082 mIsBound = true; 1083 mIsBinding = false; 1084 } 1085 mSatelliteGatewayService = ISatelliteGateway.Stub.asInterface(service); 1086 mExponentialBackoff.stop(); 1087 } 1088 1089 @Override onServiceDisconnected(ComponentName name)1090 public void onServiceDisconnected(ComponentName name) { 1091 ploge("onServiceDisconnected: Waiting for reconnect."); 1092 synchronized (mLock) { 1093 mIsBinding = false; 1094 mIsBound = false; 1095 } 1096 mSatelliteGatewayService = null; 1097 } 1098 1099 @Override onBindingDied(ComponentName name)1100 public void onBindingDied(ComponentName name) { 1101 ploge("onBindingDied: Unbinding and rebinding service."); 1102 synchronized (mLock) { 1103 mIsBound = false; 1104 mIsBinding = false; 1105 } 1106 unbindService(); 1107 mExponentialBackoff.start(); 1108 } 1109 } 1110 handleSatelliteEnablementStarted(boolean enabled)1111 private void handleSatelliteEnablementStarted(boolean enabled) { 1112 if (!enabled) { 1113 transitionTo(mDisablingState); 1114 } 1115 } 1116 isMockModemAllowed()1117 private boolean isMockModemAllowed() { 1118 return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false)); 1119 } 1120 getSatelliteStayAtListeningFromSendingMillis()1121 private long getSatelliteStayAtListeningFromSendingMillis() { 1122 if (isDemoMode()) { 1123 return DEMO_MODE_SATELLITE_STAY_AT_LISTENING_MILLIS; 1124 } else { 1125 return mContext.getResources().getInteger( 1126 R.integer.config_satellite_stay_at_listening_from_sending_millis); 1127 } 1128 } 1129 getSatelliteStayAtListeningFromReceivingMillis()1130 private long getSatelliteStayAtListeningFromReceivingMillis() { 1131 if (isDemoMode()) { 1132 return DEMO_MODE_SATELLITE_STAY_AT_LISTENING_MILLIS; 1133 } else { 1134 return mContext.getResources().getInteger( 1135 R.integer.config_satellite_stay_at_listening_from_receiving_millis); 1136 } 1137 } 1138 getSatelliteNbIotInactivityTimeoutMillis()1139 private long getSatelliteNbIotInactivityTimeoutMillis() { 1140 if (isDemoMode()) { 1141 return mContext.getResources().getInteger( 1142 R.integer.config_satellite_demo_mode_nb_iot_inactivity_timeout_millis); 1143 } else { 1144 return mContext.getResources().getInteger( 1145 R.integer.config_satellite_nb_iot_inactivity_timeout_millis); 1146 } 1147 } 1148 restartNbIotInactivityTimer()1149 private void restartNbIotInactivityTimer() { 1150 stopNbIotInactivityTimer(); 1151 startNbIotInactivityTimer(); 1152 } 1153 startNbIotInactivityTimer()1154 private void startNbIotInactivityTimer() { 1155 if (isNbIotInactivityTimerStarted()) { 1156 plogd("NB IOT inactivity timer is already started"); 1157 return; 1158 } 1159 1160 DatagramController datagramController = DatagramController.getInstance(); 1161 if (datagramController.isSendingInIdleState() 1162 && datagramController.isPollingInIdleState()) { 1163 sendMessageDelayed( 1164 EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT, 1165 mSatelliteNbIotInactivityTimeoutMillis); 1166 } 1167 } 1168 stopNbIotInactivityTimer()1169 private void stopNbIotInactivityTimer() { 1170 removeMessages(EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT); 1171 } 1172 isNbIotInactivityTimerStarted()1173 private boolean isNbIotInactivityTimerStarted() { 1174 return hasMessages(EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT); 1175 } 1176 isSatellitePersistentLoggingEnabled( @onNull Context context, @NonNull FeatureFlags featureFlags)1177 private boolean isSatellitePersistentLoggingEnabled( 1178 @NonNull Context context, @NonNull FeatureFlags featureFlags) { 1179 if (featureFlags.satellitePersistentLogging()) { 1180 return true; 1181 } 1182 try { 1183 return context.getResources().getBoolean( 1184 R.bool.config_dropboxmanager_persistent_logging_enabled); 1185 } catch (RuntimeException e) { 1186 return false; 1187 } 1188 } 1189 plogd(@onNull String log)1190 private void plogd(@NonNull String log) { 1191 logd(log); 1192 if (mPersistentLogger != null) { 1193 mPersistentLogger.debug(TAG, log); 1194 } 1195 } 1196 plogw(@onNull String log)1197 private void plogw(@NonNull String log) { 1198 logw(log); 1199 if (mPersistentLogger != null) { 1200 mPersistentLogger.warn(TAG, log); 1201 } 1202 } 1203 ploge(@onNull String log)1204 private void ploge(@NonNull String log) { 1205 loge(log); 1206 if (mPersistentLogger != null) { 1207 mPersistentLogger.error(TAG, log); 1208 } 1209 } 1210 } 1211