• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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